2014-10-31 1 views
3

Я пытаюсь написать макрос Julia, который принимает объекты Cmd и запускает их внутри цикла. Уловка заключается в том, что я хочу использовать переменные локального цикла для интерполяции в команде. Я бы написал функцию и использовал eval(), но eval() использует глобальную область видимости и поэтому не может видеть переменные локального цикла.Использование внешней командной строки Юлии внутри макросов?

Ниже приведен простой пример, демонстрирующий, как работает строка интерполяции, но команда интерполяции не удается:

macro runcmd(cmdExpr) 
    quote 
     for i in 1:2 
      println("i: $i") 
      run($cmdExpr) 
     end 
    end 
end 
@runcmd(`echo $i`) 

выходы

i: 1 
ERROR: i not defined 
in anonymous at none:5 

Если я расширяю макрос я получаю

quote # none, line 3: 
    for #261#i = 1:2 # line 4: 
     println("i: $#261#i") # line 5: 
     run(Base.cmd_gen((("echo",),(i,)))) 
    end 
end 

Я предполагаю, что часть # 261 #, отсутствующая в ссылке аргумента cmd_gen для i, равна r приподнятый к проблеме, но я не знаю точно.

+0

Просто любопытно ... Каков ваш прецедент и/или мотивация для этого? – rickhg12hs

+0

Вы читали макроэкономическую часть руководства? 'I' в вашей' quote' не будет отображаться буквально как 'i' в сгенерированном коде. – IainDunning

+0

@ rickhg12hs Я запускаю множество команд оболочки, каждая из которых находится над массивом возможных наборов данных, а командам необходимо ссылаться на имя набора данных. – slund

ответ

1

Вы правы, что проблема связана с несоответствием между индексом #261#i и ссылкой на него в echo $i. Самый простой способ решить эту проблему, чтобы избежать i, используемый в индексе:

macro runcmd(cmdExpr) 
    quote 
     for $(esc(:i)) in 1:2 
      println("i: $i") 
      run($cmdExpr) 
     end 
    end 
end 

Тогда мы получим:

julia> @runcmd(`echo $i`) 
i: 1 
1 
i: 2 
2 

Там больше обсуждение в Джулии metaprogramming documentation.

+0

Теперь я вижу, что # 261 # i означает, что я сделал локальную переменную с помощью расширителя макросов, чтобы предотвратить конфликты пространства имен. Спасибо за ответ и ссылку! – slund