2
我正在通過Dave即將推出的Elixir書籍進行工作,並且在一個練習中,我想基於一個字符的內容動態構建一個函數參考Kernel.+/2
,Kernel.-/2
等的字符串,'+'
,'-'
等等。如何動態調用Elixir中的運算符
基於另一個SO問題,我希望能夠調用apply/3
路過內核,:+和兩個數字是這樣的:
apply(Kernel, :+, [5, 7])
這不起作用,因爲(如果我的理解對不對)Kernel.+/2
是一個宏,而不是一個功能。我擡起頭的源代碼,並+
是在__op__
定義的,我可以從iex
稱之爲:
__op__(:+, 5, 7)
這工作,直到我把:+到一個變量:
iex(17)> h = list_to_atom('+')
:+
iex(18)> __op__(h, 5, 7)
** (CompileError) iex:18: undefined function __op__/3
src/elixir.erl:151: :elixir.quoted_to_erl/3
src/elixir.erl:134: :elixir.eval_forms/4
我猜測沒有辦法使用apply/3
致電__op__
。
當然,蠻力方法可以完成工作。
defp _fn(?+), do: &Kernel.+/2
defp _fn(?-), do: &Kernel.-/2
defp _fn(?*), do: &Kernel.*/2
# defp _fn(?/), do: &Kernel.//2 # Nope, guess again
defp _fn(?/), do: &div/2 # or &(&1/&2) or ("#{div &1, &2} remainder #{rem &1, &2}")
但有沒有更簡潔和動態的東西?
何塞瓦利姆釘了下面的答案。以下是在上下文中的代碼:
def calculate(str) do
{x, op, y} = _parse(str, {0, :op, 0})
apply :erlang, list_to_atom(op), [x, y]
end
defp _parse([] , acc ) , do: acc
defp _parse([h | t], {a, b, c}) when h in ?0..?9, do: _parse(t, {a, b, c * 10 + h - ?0})
defp _parse([h | t], {_, _, c}) when h in '+-*/', do: _parse(t, {c, [h], 0})
defp _parse([_ | t], acc ) , do: _parse(t, acc)
謝謝!這對我來說是訣竅。 –
順便說一下,自從&Kernel。// 2不起作用以後,對/宏來說什麼纔是正確的咒語? –
這應該這樣做:'&(Kernel ./)/ 2'(或'&(&1 /&2)') –