Search code examples
structconstructorjulia

Julia - constructor error when a field is a Vector of Functions


I created a mutable struct with a field of type Vector{Function}. When I use a constructor with only this field as an argument, I get a MethodError.

Here is minimalist example with a constructor with only the first field as argument, and a constructor with only the second field as argument.

mutable struct Human
    name::String
    actions::Vector{Function}
end

Human_name_only(name::String,
                actions = Function[]) =
                Human(name,
                      actions)

Human_func_only(actions::Vector{Function},
                name = "no_name") =
                Human(name,
                      actions)

When I'm creating a new object without a constructor, or with a constructor that only takes a string, all is well.

julia> a = Human_name_only("paul")
Human("paul", Function[])

julia> b = Human("paul", [f])
Human("paul", Function[f])

But when I use the constructor that only takes a vector of functions, I get a MethodError.

julia> c = Human_func_only([f])
ERROR: MethodError: no method matching Human_func_only(::Vector{typeof(f)})
Closest candidates are:
  Human_func_only(::Vector{Function}) at c:\Users\reiva\Documents\Julia\Mtg\TEST.jl:12
  Human_func_only(::Vector{Function}, ::Any) at c:\Users\reiva\Documents\Julia\Mtg\TEST.jl:12
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

I have tried many different ways of defining the struct and the constructor, but I always get this error, how can I solve this problem?


Solution

  • Either pass a Vector{Function} like this:

    julia> c = Human_func_only(Function[f])
    Human("no_name", Function[f])
    

    or change the method signature like this:

    julia> Human_func_only(actions::Vector{<:Function},
                           name = "no_name") =
                           Human(name,
                                 actions)
    Human_func_only (generic function with 4 methods)
    
    julia> c = Human_func_only([f])
    Human("no_name", Function[f])
    

    The problem you have is that Vector{type(f)}} is not a subtype of Vector{Function} but is a subtype of Vector{<:Function}.

    The subtyping rules in Julia are described here.