I am trying to avoid repeatedly passing a struct in my functions in order to access its fields. In Java this can be avoided by using a class and defining instance variables. What's the equivalent in Julia?
Here is some sample code where I am currently writing functions in the style of f
, which requires me to pass the struct Param, but ideally I would like to write them in the style of g
so that I don't need to pass the struct. It seems like a redundant way of writing things, especially if I have multiple functions that need access to the fields and values in Param.
struct Param
foo::Int
bar::Bool
end
f(n::Int, param::Param) = n + param.foo
g(n::Int) = n + foo
Is it accepted practice to perhaps include the function within the body of the struct?
Your function f
is considered idiomatic in Julia and in most functional programing languages. However, there are a couple patterns to be aware of that you might find useful in some situations.
First, there is syntax sugar for unpacking the properties of a struct in the argument of a function, like this:
struct A
x::Int
y::String
end
f((; x)::A, b) = x + b
julia> a = A(1, "hello");
julia> f(a, 2)
3
You can also use a similar syntax inside a function to unpack the properties of a struct:
function g(a::A, b)
(; x, y) = a
length(y) + x + b
end
julia> g(a, 2)
8
Second, in some situations it might make sense to use closures to capture the value of a struct. Here is a toy example of how you can do that:
function make_foo_bar(a::A)
(; x, y) = a
func1(b) = x + b
func2(b) = length(y) + x + b
func1, func2
end
julia> foo, bar = make_foo_bar(a)
(var"#func1#7"{Int64}(1), var"#func2#8"{String, Int64}("hello", 1))
julia> foo(2)
3
julia> bar(2)
8
Inside make_foo_bar
, I've named the functions func1
and func2
to emphasize that the names of the functions inside make_foo_bar
can be different from the names of the variables to which you assign the output functions. In this example, foo
and bar
are variables to which two different anonymous functions are assigned.