2016-06-15 2 views
4

Я работаю над макросом, чтобы динамически генерировать анонимные функции. Функция должна иметь 2 предложения. Первое предложение возвращает TRUE, когда охранник выполняется. В то время как второй - это значение по умолчанию, которое вернет FALSE, если нет совпадения с первым предложением. Например:Как создать анонимную функцию с защитой с помощью макросов?

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

Вот мой прототип макроса

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 

Проблема заключается в том, что первое условие никогда не совпадают. Это тот ввод, который я использовал для проверки моего макроса в REPL RE:

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 

Любые предложения?

Спасибо заранее, Умберто

ответ

1

Я решил свою проблему благодаря помощи ребята на канале слабины и подсказке CoderDennis.

Это было неправильное представление с моей стороны. Мне не нужно было использовать макросы. Мне просто нужна была регулярная функция.

Вот окончательный вариант моей функции для создания анонимных функций с охранником:

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

У меня нет полного ответа пока нет, но вот как увидеть AST макрос возвращается:

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) не выполняют то, что вы ожидаете от них в своем макросе.

Мне не хватает специалиста по макроэкономике, чтобы знать, как делать то, что вы пытаетесь сделать, но просто захотелось разделить чат отладки макросов. Если я смогу понять, как заставить его работать, я тоже поделюсь этим.

+0

Спасибо за ваш кончик и время Это мой первый раз, работая с Elixir's Macro System – Humberto

+0

Я тестировал тело моей макрофункции на iex, и я получаю правильный АСТ. Я не сейчас, что мне не хватает в моей макрофункции :( – Humberto

+0

Я использую этот [пост] (http: //stackoverflow.com/questions/24849774/creating-anonymous-functions-via-macros) в качестве руководства, но кажется, что я делаю что-то неправильно – Humberto

Смежные вопросы