4
votes

The code below shows an example of what I'm asking about: why Map, Enum, etc... can't be used within guard clauses or inside my own macros.

defmodule GuardMod do
    defmacro has_any_key(arg, keys) do
        quote do
            Map.keys(unquote(arg), unquote(keys)) |> Enum.any?
        end
    end
end

defmodule OtherMod do
    import GuardMod

    @doc """
    has_any_key/2 is allowed, but Map.keys or Map.any not
    """
    def fn1(list) when has_any_key(list, [:key1, :key2]), do: :nothing
end
1
The answers to this question are relevant: stackoverflow.com/questions/11177109/…Dogbert
It makes sense, since Elixir and Erlang guards are the same implementation.Marcos Costa Pinto

1 Answers

7
votes

It's a compromise to allow multi function head dispatching to be "fast".

The type of functions allowed in guards all have a limited runtime or reduction count. If you allow arbitrary functions in guards, you have to deal with the case in which the guard evaluation does not finish before the current process exceeds it current execution slice. ( Or potentially even worse cases a race condition because it requires input from another process).