2016-09-28 4 views
5

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

type Test 
    ex 
end 

который содержит выражение. Я хочу создать конструктор, где origex = :(a * b) по умолчанию является аргументом ключевого слова. Я попытался

@eval :(Test(ex=$origex) = Test(origex)) 

Но если вы посмотрите на выражение, что делает:

Test(ex=a * b) = begin # console, line 1: 
    Test(origex) 
end 

вы видите, что это не будет работать, потому что a*b должен еще быть выражением. Так что я попытался

@eval :(Test(ex=:($origex)) = Test(origex)) 

, но это имеет странное выражение

Test(ex=$(Expr(:quote, :($(Expr(:$, :origex)))))) = begin # console, line 1: 
    Test(origex) 
end 

, который также не будет eval. Вместо этого мне нужно, чтобы получить

Test(ex=:(a * b)) = begin # console, line 1: 
    Test(origex) 
end 

как выражение для Eval, но я не знаю, как получить это выражение в выражение.

ответ

6

Я думаю, что следующее, что вы хотите. У вас, кажется, было несколько ошибок:

julia> type Test 
     ex::Expr 
     end 

julia> orig_ex = :(a + b) 
:(a + b) 

julia> new_ex = Meta.quot(orig_ex) 
:($(Expr(:quote, :(a + b)))) 

julia> code = :(Test(; ex=$new_ex) = Test(ex)) 
:(Test(; ex=$(Expr(:quote, :(a + b)))) = begin # REPL[4], line 1: 
      Test(ex) 
     end) 

julia> eval(code) 
Test 

julia> Test() 
Test(:(a + b)) 
+1

Спасибо. Это сработало красиво. Что такое 'Meta.quot', и почему он отличается от: (orig_ex)? –

+1

@ChrisRackauckas 'Meta.quot (ex)' просто 'Expr (: quote, ex)': 'julia> ex =: (a + b); @assert Meta.quot (ex) == Expr (: quote, ex) ' – SalchiPapa

+0

Meta.quot добавляет еще один уровень цитирования. Как вы нашли, когда вы интерполируете, просто использовать: (orig_ex) недостаточно для сохранения цитирования. Эти вещи довольно сложны, чтобы поправиться, по моему опыту! –

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