How to create an anonymous function with macro protection?

I am working on a macro to dynamically generate anonymous functions. The function should have 2 sentences. The first sentence returns TRUE when the guard is executed. While the second is the default value, which will return FALSE if there is no match with the first sentence. For instance:

fn 
  xfield when xfield > 2 -> true
  _ -> false
end

Here is my macro prototype

defmacro condition_function(field, guard) do
  clause1 =  quote do: (unquote(field) when unquote(guard) -> true)
  clause2 =  quote do: (_ -> false)
  fun_clauses =  clause1 ++ clause2
  {:fn, [], fun_clauses}
end

The problem is that the first sentence never matches. This is the input I used to test my macro in the Elixir REPL:

iex(84)> myfield = quote do: xfield
{:xfield, [], Elixir}
iex(85)> myguard = quote do: xfield > 2
{:>, [context: Elixir, import: Kernel], [{:xfield, [], Elixir}, 2]}
iex(86)> myFun = Builder.condition_function(myfield, myguard)
#Function<6.50752066/1 in :erl_eval.expr/5>
iex(87)> myFun.(2)
false
iex(88)> myFun.(5)
false

Any suggestions?

Thanks in advance, Umberto

+4
source share
2 answers

I solved my problem thanks to the help of the guys on the laxative channel and the help of CoderDennis.

. . .

guard:

def anonym_function(field, constraint) do
    clause1 =  quote do: (unquote(field) when unquote(constraint) -> true)
    clause2 =  quote do: (_ -> false)
    fun_clauses =  clause1 ++ clause2
    {fun, _} = Code.eval_quoted({:fn, [], fun_clauses})
    fun
end

: (

+1

, , :

defmacro condition_function(field, guard) do
  clause1 =  quote do: (unquote(field) when unquote(guard) -> true)
  clause2 =  quote do: (_ -> false)
  fun_clauses =  clause1 ++ clause2
  result = {:fn, [], fun_clauses}
  IO.inspect(result)
  result
end

iex. , , :

iex> quote do: fn
...> xfield when xfield > 2 -> true
...> _ -> false
...> end
{:fn, [],
 [{:->, [],
   [[{:when, [],
      [{:xfield, [], Elixir},
       {:>, [context: Elixir, import: Kernel], [{:xfield, [], Elixir}, 2]}]}],
    true]}, {:->, [], [[{:_, [], Elixir}], false]}]}

IO.inspect :

iex(9)> myFun = Builder.condition_function(myfield, myguard)
{:fn, [],
 [{:->, [],
   [[{:when, [], [{:myfield, [line: 9], nil}, {:myguard, [line: 9], nil}]}],
    true]}, {:->, [], [[{:_, [], Builder}], false]}]}

( 9 iex.)

, unquote(myfield) unquote(myguard) , .

, , , , . , , .

+1

All Articles