How to apply is_nil

applying is_integer works fine:

iex> apply(Kernel, :is_integer, [1])
true

but applying is_nil produces an error:

iex> apply(Kernel, :is_nil, [nil])
** (UndefinedFunctionError) function Kernel.is_nil/1 is undefined or private. However there is a macro with the same name and arity. Be sure to require Kernel if you intend to invoke this macro
    (elixir) Kernel.is_nil(nil)
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (iex) lib/iex/evaluator.ex:250: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:230: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:208: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:94: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:24: IEx.Evaluator.init/4
    (iex) lib/iex/pry.ex:64: IEx.Pry.pry/2
    (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
    test/utils_test.exs:29: UtilsTest."test parseable fields"/1
    (ex_unit) lib/ex_unit/runner.ex:306: ExUnit.Runner.exec_test/1
    (stdlib) timer.erl:166: :timer.tc/1
    (ex_unit) lib/ex_unit/runner.ex:245: anonymous fn/4 in ExUnit.Runner.spawn_test/3

Why is this? and how am I able to apply the is_nil function?

From the error:

However there is a macro with the same name and arity. Be sure to require Kernel if you intend to invoke this macro

So is_nil/1 is a macro, and apply/3 works with functions.

You can wrap is_nil/1 in a function and call apply/3 with it:

args = [nil]
apply(fn x -> is_nil(x) end, args)
#=> true

# or in using shorter version
apply(&is_nil/1, args)
#=> true

In both cases fn x -> is_nil(x) end expands to fn x -> x == nil end.

2 Likes