如何在不使用eval的情况下从符号中获取函数?

时间:2015-03-11 18:18:09

标签: julia

我有一个代表要调用的函数名称的符号:

julia> func_sym = :tanh

我可以使用该符号来获取tanh函数并使用:

调用它
julia> eval(func_sym)(2)
0.9640275800758169

但我宁愿避免使用'eval',因为它会被多次调用而且价格昂贵(而且func_sym可能有几个不同的值,具体取决于上下文)。

Ruby中的IIRC你可以这样说:

obj.send(func_sym, args)

朱莉娅有类似的东西吗?

编辑:有关为什么我有符号表示函数的更多细节:

我有一个包含激活功能的类型(来自神经网络),最初我把它作为一个功能包括在内:

type NeuralLayer
  weights::Matrix{Float32}
  biases::Vector{Float32}
  a_func::Function
end

但是,我需要使用JLD将这些内容序列化为文件,但是无法序列化函数,所以我选择了符号:

type NeuralLayer
  weights::Matrix{Float32}
  biases::Vector{Float32}
  a_func::Symbol
end

目前我使用上面的eval方法来调用激活功能。有一些NeuralLayers集合,每个都可以拥有它自己的激活功能。

2 个答案:

答案 0 :(得分:7)

@ Isaiah的回答是正确的;在编辑原始问题之后,或许更是如此。要详细说明并使其更具针对您的案例:我将您的NeuralLayer类型更改为参数化:

type NeuralLayer{func_type}
  weights::Matrix{Float32}
  biases::Vector{Float32}
end

由于func_type未出现在字段类型中,因此构造函数将要求您明确指定它:layer = NeuralLayer{:excitatory}(w, b)。这里的一个限制是您无法修改类型参数。

现在,func_type可能是一个符号(就像你现在正在做的那样),或者它可能是一个功能更相关的参数(或参数)来调整你的激活功能。然后你定义你的激活函数:

# If you define your NeuralLayer with just one parameter:
activation(layer::NeuralLayer{:inhibitory}) = …
activation(layer::NeuralLayer{:excitatory}) = …
# Or if you want to use several physiological parameters instead:
activation{g_K,g_Na,g_l}(layer::NeuralLayer{g_K,g_Na,g_l} = f(g_K, g_Na, g_l)

关键是功能和行为是外部到数据。使用类型定义和抽象类型层次结构来定义行为,如在外部函数中编码的那样......但仅在类型中存储数据本身。这与Python或其他强烈面向对象的范例截然不同,需要一些时间来习惯。

答案 1 :(得分:4)

  

但我宁愿避免使用'eval',因为它会被多次调用而且价格昂贵(而且func_sym可能有几个不同的值,具体取决于上下文)。

这种动态调度在Julia中是可行的,但不推荐。根据上下文更改'func_sym'的值会导致类型推断以及方法特化和内联失败。相反,建议的方法是使用multiple dispatch,详见手册的Methods部分。