Open modules in Elixir?

Ruby has open classes that are very convenient (albeit offended by some), and Elixir borrows Ruby a lot, so I expected Elixir to let me open the module again and add macros to it after closing it, but this doesn’t work like I tried . Is there any way to do this? Is this feature still available in Elixir?

To make this concrete, let's take an example from Chris McCord. Elixir metaprogramming:

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 

If I then add a macro to subtract

 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 

I get a warning that I am overriding the Math module and the initially defined macros fail. Thus, it is obvious that my approach is not right, but is there another approach that can achieve the same goal?

+8
elixir
source share
1 answer

You cannot reopen the module. Because Elixir is a compiled language, the path from source to executable is one-way. Mechanisms that modify code, such as macros, are evaluated at compile time. However, Elixir allows you to do hot swapping of code, i.e. E. You can replace the compiled module at runtime.

I think this has some interesting implications. You get the opportunity to change the program at runtime - in practice, you control the source code and therefore you can change individual parts of the module without changing the others. However, I like the idea of ​​having everything in one place. In Elixir, when you look at a module, you know exactly what you have.

So, if this question only concerns a convenient development workflow, the closer you will use Ruby to add methods to the class to save your module in a file and recompile it from iex as you go.


* Strictly speaking, you may not know exactly which code works just by looking at the module. When you use protocols, you also need to look at all protocol implementations that can be scattered throughout your code base or, even worse, they can be distributed between several applications.

+17
source share

All Articles