Is this a function or not?

Hello. I am new here. I just created a new Hello World project with mix.

defmodule HelloWorld do
  def hello do
    :world
  end
end

It seems obvious to me that hello is a function.

But then I see that is_function(HelloWorld.hello) returns false.

What am I missing?

Problem is that when you write HelloWorld.hello, then it will be immediately executed and the output :world will be checked if it is a function.

2 Likes

Elixir allows you to call functions without parentheses, so HelloWorld.hello actually invokes a zero-arity function that returns :world, which is not a function.

You can capture functions with the & operator to pass the function around as a value. You can capture a named function with &Module.function/arity. For your hello function that would look like &HelloWorld.hello/0.

So what you’re trying to do would instead look like is_function(&HelloWorld.hello/0), though typing that literally would always return true. If you can capture a function, it’s a function.

3 Likes

@egze nice! Here is the proof:

iex(1)> defmodule HelloWorld do
...(1)>   def hello do
...(1)>     IO.puts("Hi")
...(1)>     :world
...(1)>   end
...(1)> end
{:module, HelloWorld,
 <<70, 79, 82, 49, 0, 0, 4, 232, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 151,
   0, 0, 0, 16, 17, 69, 108, 105, 120, 105, 114, 46, 72, 101, 108, 108, 111, 87,
   111, 114, 108, 100, 8, 95, 95, 105, 110, ...>>, {:hello, 0}}
iex(2)> is_function(HelloWorld.hello)
Hi
false

Cool, I suspected that it was something like that. Thanks!

Maybe it could be mentioned here or here?

There might be a better way to make that visible. Maybe the best introduction I’ve seen is in the “getting started” guide on the Elixir site: https://elixir-lang.org/getting-started/modules-and-functions.html#function-capturing

1 Like