classstructjuliainstance-variablesmultiple-dispatch

What is the Julia equivalent to classes and instance variables in Java?


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?


Solution

  • 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.