Ruby 有开放类,非常方便(尽管受到一些人的谩骂),而 Elixir 大量借鉴了 Ruby,所以我希望 Elixir 允许我重新打开一个模块并在关闭它后向其中添加宏,但这在我尝试的方式。有什么方法可以做到这一点吗? Elixir 中是否提供此功能?
为了具体说明这一点,让我们以 Chris McCord 的元编程 Elixir 为例:
defmodule Math do
defmacro say({:+, _, [lhs, rhs]}) do
quote do
lhs = unquote(lhs)
rhs = unquote(rhs)
result = lhs + rhs
IO.puts "#{lhs} plus #{rhs} is #{result}"
result
end
end
defmacro say({:*, _, [lhs, rhs]}) do
quote do
lhs = unquote(lhs)
rhs = unquote(rhs)
result = lhs * rhs
IO.puts "#{lhs} times #{rhs} is #{result}"
result
end
end
end
如果我然后添加一个宏来进行减法
defmodule Math do
defmacro say({:-, _, [lhs, rhs]}) do
quote do
lhs = unquote(lhs)
rhs = unquote(rhs)
result = lhs - rhs
IO.puts "#{lhs} minus #{rhs} is #{result}"
result
end
end
end
我收到一条警告,提示我正在重新定义数学模块,并且最初定义的宏失败。显然我的方法不是正确的,但是还有另一种方法可以实现相同的目标吗?
您无法重新打开模块。由于 Elixir 是一种编译语言,因此从源代码到可执行表示的方式是单向的。改变代码的机制(例如宏)在编译期间进行评估。然而,Elixir 允许您进行热代码交换,即。 e.您可以在运行时替换已编译的模块。
我认为这有一些有趣的含义。您能够在运行时更改程序 - 实际上,您可以控制源代码,因此您可以交换模块的各个部分而不更改其他部分。尽管如此,我还是喜欢将一切都集中在一个地方的想法。在 Elixir 中,当您查看模块时,您会确切地知道自己拥有什么*。
因此,如果这个问题只是关于方便的开发工作流程,那么您最接近 Ruby 向类添加方法的能力就是将模块保存在文件中,并在使用时从 iex 重新编译它。
* 严格来说,你可能not只需查看模块即可准确了解正在运行的代码。当您使用协议时,您还需要查看所有协议实现,这些实现可能分散在您的代码库中,或者更糟糕的是,它们可能分布在多个应用程序中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)