繁体   English   中英

在Elixir中打开模块?

[英]Open modules in Elixir?

Ruby有开放的类,非常方便(虽然受到一些人的谴责),Elixir大量借用Ruby,所以我希望Elixir允许我重新打开一个模块并在关闭后添加宏,但这不起作用我试过的方式。 有办法做到这一点吗? Elixir中是否提供此功能?

为了具体化,让我们以Chris McCord的Metaprogramming 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

我得到一个警告,我正在重新定义模块Math,并且最初定义的宏会失败。 显然我的方法不是正确的方法,但是有另一种方法可以实现同样的目标吗?

您无法重新打开模块。 由于Elixir是一种编译语言,从源代码到可执行表示的方式是单向的。 在编译期间会评估更改代码的机制,例如宏。 但是,Elixir允许您进行热代码交换,即您可以在运行时替换已编译的模块。

我认为这有一些有趣的含义。 您可以在运行时更改程序 - 实际上,您可以控制源代码,这样您就可以更换模块的各个部分而无需更改其他部分。 不过,我喜欢把所有东西放在一个地方的想法。 在Elixir中,当你看一个模块时,你确切地知道你有什么*。

因此,如果这个问题仅仅是关于一个方便的开发工作流程 - 最接近Ruby的方法是将类添加到类中的方法是将模块保存在文件中并随时从iex重新编译它。


*严格来说,只需查看模块,您可能无法确切知道正在运行的代码。 当您使用协议时,您还需要查看所有协议实现,这些实现可能分散在整个代码库中,或者更糟糕的是,它们可能分布在多个应用程序中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM