首页 > 解决方案 > Julia 相当于一个 lisp 符号宏?

问题描述

我正在尝试做 Lisp 黑客所说的“符号宏”。也就是说,这就是我现在使用的:

global ghypers = Dict()
macro hyp(variable, value); ghypers[:($variable)] = :($value); end
macro hyp(variable); ghypers[:($variable)]; end
@hyp foo 5
println(ghypers)
println(@hyp foo)
println(@hyp(foo)+1)

到目前为止一切顺利,但最后一件事是丑陋的,我想这样做:

@foo+1

有点像这样:

macro foo(); ghypers[:foo]; end
println(@foo)
println(@foo()+1)

关闭,并且工作,但不是我想要的,这又是:

println(@foo+1) 
MethodError: no method matching @foo(::LineNumberNode, ::Module, ::Expr)

除了那行不通。

Lisp 有符号宏的概念,您可以在其中将宏扩展绑定到符号,如 foo,以便符号将扩展为值。

现在,一个明显但同样糟糕(在不卫生的意义上)的方法就是将全局 var foo 绑定到值,但我不希望全局(或者,更确切地说,我希望它们本地化在 ghypers 中)。

有什么办法可以做我在 Julia 中寻求的事情吗?

(<flame> 40 多年来一直是一个快乐的 lisp 露营者,Julia 是第一个我可以说我实际上甚至有点喜欢的编程语言。但没有意识到同音性的重要性,他们的宏系统是......好吧,在我看来,一团糟,Lisp 像雨水一样清澈。</flame> :-)

标签: macrosjulialisp

解决方案


有两种直接的方法。如果事物是​​卫生的并且引用透明,则只需使用一个const值。这在您的示例中不起作用。

否则,您必须在调用语法中使用宏:@foo(). 没有周围的,这就是 Julia 语法的工作方式。虽然我也不建议这样做。

但是一个更好的选择,恕我直言,将是一个“照应上下文宏”,例如:

@withhyper (stuff) begin
    println(foo+1) 
end

在哪里fooesc某个本地范围内的名称。将块扩展为

let foo = setup_hyper(stuff, ...)
    println(foo+1)
end

推荐阅读