Reputation: 1381
The name of the struct to instantiate will be passed by the caller to my program. Then I would need to instantiate the corresponding struct for the same for further processing.
For example, if the struct is defined like this
struct A end
and I have a function defined as
function load(struct_name::AbstractString)
if struct_name == "A"
return A()
elseif struct_name == "B"
return B()
elseif ..... # and so on
end
end
it will work. But is there a more direct way like return struct_name()
instead of having n number of if else statements? I see that Julia supports reflection. How can that be used to support the above use case?
Upvotes: 2
Views: 1571
Reputation: 7893
You could use a macro instead:
julia> module Load
export @load
macro load(struct_name::Symbol)
return :($(esc(struct_name))())
end
end
Main.Load
julia> using Main.Load: @load
julia> struct A end
julia> struct B end
julia> @load A
A()
julia> @macroexpand @load B
:(B())
julia> @load C
ERROR: UndefVarError: C not defined
Stacktrace:
[1] top-level scope at none:0
Upvotes: 1
Reputation: 4571
An example of dictionary-based dispatch. Dict("a" => A, "b" => B)[tag]
selects a constructor, and ()
calls it.
struct A end
struct B end
function dispatch(tag)
return Dict("a" => A, "b" => B)[tag]()
end
@assert dispatch("a") == A()
If you care about default values to handle unexpected parameter, for example dispatch('zzz')
,
you can make recourse to get()
.
As a side note about risks of eval()
there is a small collection of powerful warning references in a neighboring Python question. In short, eval()
is a big security hole and a 'smell' (warning sign) for a questionable design of a program.
Upvotes: 1
Reputation: 69949
I would recommend not doing it in production code, but you can do the following:
function load(struct_name::AbstractString)
invoke(eval(Symbol(struct_name)),Tuple{})
end
strut_name
via eval
will get resolved in the global scope of the module.
It is safer to use a dictionary as @EPo suggested.
Upvotes: 3