18

Is there an equivalent for retrieving the name of a function just like like __MODULE__ retrieves the name of a Module in Elixir/Erlang?

Example:

defmodule Demo do
  def home_menu do
    module_name = __MODULE__
    func_name = :home_menu 
    # is there a __FUNCTION__
  end
End

EDITED

The selected answer works,

but calling the returned function name with apply/3 yields this error:

[error] %UndefinedFunctionError{arity: 4, exports: nil, function: :public_home, module: Demo, reason: nil}

I have a function :

defp public_home(u, m, msg, reset) do

end

The function in question will strictly be called within its module.

Is there a way to dynamically call a private function by name within its own module?

6
  • 3
    Predefined Macros Commented Nov 14, 2017 at 8:42
  • @OnorioCatenacci I see your point. The function in question will strictly be called within its module. is there a way to dynamically call a private function by name within its own module? Commented Nov 14, 2017 at 19:43
  • Are you recursively trying to call the function from within itself? In this particular case while I can see the appeal of not having to specify the function name, I'd say you should just bite the bullet and hard code it in the body of the function. Commented Nov 14, 2017 at 19:43
  • @OnorioCatenacci no. I store the previous and current function a user executes. I need to be able to use this to go back, and forward. Each method equates to a menu/page. I am trying to use apply to call the user.current or user.previous functions Commented Nov 14, 2017 at 19:47
  • Then what about Code.eval_string? hexdocs.pm/elixir/Code.html#eval_string/3 Would that work for what you need? Commented Nov 14, 2017 at 19:51

4 Answers 4

31
▶ defmodule M, do: def m, do: __ENV__.function  
▶ M.m                                                 
#⇒ {:m, 0}

Essentially, __ENV__ structure contains everything you might need.

Sign up to request clarification or add additional context in comments.

3 Comments

i'm a bit confused about this, i am able to get the function name, but calling it with apply/3 fails: [error] %UndefinedFunctionError{arity: 4, exports: nil, function: :public_home, module: Demo, reason: nil}
Is it public? Did you pattern match and pass the name only?
Private functions are not accessible from outside.
4

Yes, there is. In Erlang there are several predefined macros that should be able to provide the information you need:

% The name of the current function
?FUNCTION_NAME

% The arity of the current function (remember name alone isn't enough to identify a function in Erlang/Elixir)
?FUNCTION_ARITY 

% The file name of the current module
?FILE 

% The line number of the current line
?LINE 

Source: http://erlang.org/doc/reference_manual/macros.html#id85926

3 Comments

@do you know the elixir equivalent for each?
No, but it looks like @mudasobwa's answer works in Elixir. __ENV__.function is the equivalent of {?FUNCTION_NAME, ?FUNCTION_ARITY}. This is one area where Elixir and Erlang differ quite a bit, so it's going to be hard to find something that works exactly the same between both of them.
3

To add to Aleksei's answer, here is an example of a macro, f_name(), that returns just the name of the function.

So if you use it inside a function, like this:

def my_very_important_function() do
   Logger.info("#{f_name()}: about to do important things")
   Logger.info("#{f_name()}: important things, all done")
end

you will get a log statement similar to this:

my_very_important_function: about to do important things
my_very_important_function: important things, all done

Details:

Here is the definition of the macro:

defmodule Helper do
  defmacro f_name() do
    elem(__CALLER__.function, 0)
  end
end

(__CALLER__ is just like __ENV__, but it's the environment of the caller.)

And here is how the macro can be used in a module:

defmodule ImportantCodes do
  require Logger
  import Helper, only: [f_name: 0]

  def my_very_important_function() do
     Logger.info("#{f_name()}: doing very important things here")
  end
end

1 Comment

when you find a good answer, and then realize it's yours, from a couple of years ago. ; )
1
__ENV__.function |> elem(0) 

Will result with the name of the function you are currently in.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.