#julia #metaprogramming #symbols
Вопрос:
Мне нужно сгенерировать call
выражение, в котором одним из аргументов ключевого слова является символ. Я могу ввести это явно так:
juliagt; dump(:(func(something; a=:b))) Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol func 2: Expr head: Symbol parameters args: Array{Any}((1,)) 1: Expr head: Symbol kw args: Array{Any}((2,)) 1: Symbol a 2: QuoteNode value: Symbol b 3: Symbol something
Обратите внимание на аргумент ключевого a
слова, который имеет значение symbol :b
Что я хочу сделать, так это сгенерировать это выражение программно, где :b
деталь интерполируется, скажем, из некоторой переменной x
.
Я попробовал это
juliagt; x = :u :u juliagt; dump(:(func(something; a=$(x)))) Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol func 2: Expr head: Symbol parameters args: Array{Any}((1,)) 1: Expr head: Symbol kw args: Array{Any}((2,)) 1: Symbol a 2: Symbol u 3: Symbol something
но вместо того, чтобы получить значение a QuoteNode
со значением Symbol u
, я просто получаю символ u. Это не сработает, потому что, когда я оцениваю выражение, оно ищет переменную u
, но должно просто вставлять Symbol u
ее . Я пробовал кое — что другое, но не могу заставить это работать. Спасибо
Комментарии:
1. Просто заверните его в
QuoteNode
или используйтеMeta.quot
::(func(something; a=$(QuoteNode(x))))
.2. @pfitzseb Сделайте это ответом, единственное, что я бы добавил, — это показать результат
dump( :(a :u) )
vsdump( :(a u) )
, чтобы проиллюстрировать разницу.3. @dantheman Я также отмечу, что интерполяция
:(a $x)
идентичнаExpr(:call, : , :a, x)
. Таким образом, вы вставляете Символ:u
в выражение, он просто обрабатывается как переменная во время вычисления, как и все остальные символы. Поэтому, чтобы сохранить его в качестве символа при оценке, вам просто нужно было завернуть его в QuoteNode. Остерегайтесь этих интуитивных способов обертывания::($x)
,$(:x)
, и:x
; они могут показаться правильными, ноdump
покажут, что вы вставляете символ:x
, а не:u
.4. @pfitzseb Да, это сработало. Я мог бы поклясться, что пытался это сделать, но, думаю, нет. Спасибо
Ответ №1:
Вы можете обернуть x
QuoteNode
вручную или использовать Meta.quot
(что создает Expr(:quote, ...)
):
juliagt; x = :u; juliagt; dump(:(func(something; a=$(QuoteNode(x))))) Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol func 2: Expr head: Symbol parameters args: Array{Any}((1,)) 1: Expr head: Symbol kw args: Array{Any}((2,)) 1: Symbol a 2: QuoteNode value: Symbol u 3: Symbol something juliagt; func(x; a) = x, a func (generic function with 1 method) juliagt; eval(:(func(something; a=$(QuoteNode(x))))) (something, :u) juliagt; eval(:(func(something; a=$(Meta.quot(x))))) (something, :u)