$handle_undefined_function in Elixir/Erlang
I was searching for ways to implement Ruby's
Elixir the other day. Then I ran into this package:
andrewvy/method_missing: Elixir Library for dynamic code
execution. And it implements exactly what I want: a
function to dynamically generate function body for what's not defined
defmodule Dog do use MethodMissing def method_missing(func, _args) do func_name = Atom.to_string(func) cond do Regex.match?(~r/bark|woof/, func_name) -> "WOOF" true -> "?" end end end Dog.bark() # > "WOOF" Dog.woof() # > "WOOF" Dog.meow() # > "?"
I was curious about how it was implemented in Elixir, so I looked into
lib directory. Surprisingly, it's fairly simple:
defmodule MethodMissing do defmacro __using__(_opts) do quote do def method_missing(_func, _args) do end def unquote(:"$handle_undefined_function")(func, args), do: method_missing(func, args) defoverridable method_missing: 2 end end end
From this implementation, we can know that we don't even need to use
this package to get
method_missing in Elixir. (The name
method_missing is not very functional either.)
All we need to do is to define
method_missing, it will receive two arguments, one for the
function name, and one for the list of arguments.
Again, I want to praise Elixir/Erlang when I discovered this feature. Almost every time I miss something in Ruby, Elixir already has a solution for that.
Although, I doubt that
$handle_undefined_function will be as popular
in the Elixir community as
method_missing in the Ruby community.
Elixir is a language that emphasize on explicity.
Looking for behaviors that are hidden under
$handle_undefined_functionis a long trip.
This kind of meta-programming would always be the last resort for an Elixir developer.
$handle_undefined_functionmight not be as efficient as
When we use
method_missing, we usually use
define_methodto speed up future method calls.
But Elixir, as a compiled language, doesn't have a function like
define_methodto generate new functions. So it may be much slower.
After all, I'm very glad that Elixir/Erlang provide us an option to do this kind of meta-programming. And I can't wait to see more surprises Elixir/Erlang bring to me in the future.