Reputation: 559
Suppose I have two functions:
function func_one(data, pars):
---
end
function func_two(data, pars):
---
end
Each function requires data and pars, but not necessarily of the same dimension, so I create
data_one = []
data_two = []
pars_one = []
pars_two = []
Next, I have a string variable, say name, that can be either "one" or "two" and would be used to select what type of triplet (func, data, pars) is going to be used later when I call everything. For example
name = "one"
and then I have
func = "func_" * name
data = "data_" * name
pars = "pars_" * name
Then I would like to call such combination, for example
MainFunction(func,data,pars)
In reality I have many more than two possible triplets (func, data, pars). Of course at this moment this doesn't work because (func, data, pars) are strings, but I would like them to point to the corresponding function and variables. I want to do this so that a user can just change the string name, and then everything else is selected appropiately. How to do this (in Julia)?
Upvotes: 0
Views: 722
Reputation: 42214
While Tasos is right that normally you should use functions, lambdas or data structure for that purpose I understand your question is actually about meta-programming. Here is how to do it:
Let us start by preparing functions and variables:
function main_fun(f,data,pars)
println([f(),data,pars])
end
function f1()
return "hello from f1"
end
data1 = "I'm data1"
pars1 = "I'm pars1"
Now, following your question, we assume that the name of actual parameters are hold in String
s - we need to convert them to Symbol
s:
f_name, data_name, pars_name = Symbol.(("f1","data1","pars1"))
Create the code (note the use of interpolation):
code = :(main_fun($f_name,$data_name,$pars_name))
Now let's get the things rolling (this is a sample console output):
julia> Main.eval(code)
["hello from f1", "that is data1", "that is pars1"]
Note that Main.eval
needs to compile the code and it takes time.
Upvotes: 2
Reputation: 22215
You are thinking along the lines of evaluating strings, which is always a bad idea. Instead, focus on creating appropriate structures. If you really must use strings (even though thinking about this as arrays would be preferable), you can use said strings as keys in a dictionary, e.g.:
funcs = Dict{String, Function}(); #> Dict{String,Function} with 0 entries
funcs["one"] = (data, pars) -> print("Doing stuff with provided data and pars");
funcs["two"] = (data, pars) -> print("Doing something else with provided data and pars");
data = Dict{String, Any}(); #> Dict{String,Any} with 0 entries
data["one"] = [1 2 3 4 5];
data["two"] = [1;2;3;4;5];
pars = Dict{String, Any}(); #> Dict{String,Any} with 0 entries
pars["one"] = "Use turbo encabulator model";
pars["two"] = "Use encaboturbolation semantics";
# Use it
funcs["one"](data["one"], pars["one"]) #> prints "Doing stuff with provided data and pars"
As you can see from above, creating your functions as 'lambdas' makes it easy to assign them to a dictionary element. If you need multi-line functions, you can use a begin ... end
block to achieve this.
Upvotes: 2