Yet another "how to pass multiple parameters to a function" post

Apologies for the n-th post on this topic (#1, #2, #3, etc. etc).I simply don’t get it and feel overwhelmed by all choices of how to pass parameters to a function (positional arguments, optional keyword arguments, named tuples with varargs, Parameters.jl).

I am developing a package, which you call a function to estimate a model. This function takes in some parameters which have default values. Even after reading most threads on the topic, I don’t understand, where do I put the structure with parameters to pass along in functions? This is if I am not using keyword arguments.

Here is my current code for a file model.jl that uses my package: Load packages, load data, use the function.

using Revise
using BEAVAR
using CSV
using Parameters


Y_20 = readdlm("data/FRED_Chan2019.txt", ',');

@with_kw struct hypChan2020
    c1::Float64 = 0.04; # hyperparameter on own lags
    c2::Float64 = 0.01; # hyperparameter on other lags
    c3::Float64 = 100;  # hyperparameter on the constant
end

store_beta = Chan2020_LBA(Y_4,hypChan2020)

where my function looks like this:

module BEAVAR
function Chan2020_LBA(YY,hypChan2020;p::Integer=4,nburn::Integer=1000,nsave::Integer=2000)
...
end
emd

I would actually like to have a larger struct hypChan2020 and not have it in the file, while the user should still be able to change the parameters. I am currently achieving this (for other parameters) with keyword arguments, and I could put c1,c2,c3, but with many it gets cumbersome.

What is the best way to pass a structure, which is not in the main .jl file that gets called in the function and the user doesn’t see it? More accurately, my question is where should I put the strcuture?

  • I cannot put `@with_kw’ in the function directly because I get an error that macros cannot be in the local scope.

  • Should I have a separate file for the options and include it? E.g.

Y_20 = readdlm("data/FRED_Chan2019.txt", ',');

include('fileWithKWMacro.jl')

store_beta = Chan2020_LBA(Y_4,hypChan2020)
  • I tried putting the macro in the module but I also couldn’t get it to work and that would be weird as I would have different structures for different models and I would like each to be associated with the function that needs it.

Ideally I want the user to just load the data and choose the function, i.e. they should be able to write their own model.jl without the need to include a specific file or call Parameters.jl (which I call in the module later anyways for unpacking).

Edits: rephrasing the question for clarity

This should be inside your module, and the name of the struct should be public, probably exported. The user must create one instance of that struct, and pass it to the function.

In the example you are passing the type.

The function can or cannot set a default value for the parameters, with options::hypChan2020=hypChan2020() as a keyword or optional positional argument.

(This alternative is what I described here: How to allow users to safely change package "constants"? - #6 by lmiq)

1 Like

You can also note that Parameters.jl is not necessary for structure unpacking. You can use this syntax

struct MyStruct
  x::Int
  y::String
end

s = MyStruct(1,"test")
(; x, y) = s
1 Like

I see, i definitely didn’t export it when I tried putting it in the module and didn’t create an instance.

Thank you, I will try and report back.