单一命名空间为何会导致不卫生的宏? (在 LISP 中)

发布于 2024-09-14 13:41:59 字数 387 浏览 4 评论 0原文

有人声称 LISP 中的单一名称空间会导致宏不卫生。 http://community.schemewiki.org/?hygiene-versus-gensym

< a href="http://www.nhplace.com/kent/Papers/Technical-Issues.html" rel="nofollow noreferrer">http://www.nhplace.com/kent/Papers/Technical-Issues.html

拥有单一、双重或多个命名空间到底是什么导致了宏观卫生?

Some claim that a single namespace in LISP leads to unhygienic macros.
http://community.schemewiki.org/?hygiene-versus-gensym

http://www.nhplace.com/kent/Papers/Technical-Issues.html

What precisely is it about having single, dual or multiple namespaces that leads to macro hygiene?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

等待圉鍢 2024-09-21 13:41:59

Lisp-2 意味着你有两个命名空间:一个用于函数,一个用于其他东西。

这意味着您不太可能无意中重新绑定宏中的函数值(或 var 值)。

在 Lisp-1 中,由于只有一个名称空间,因此(从统计上看,但实际上并非如此)命中现有定义的可能性是原来的两倍。

事实上,Lisp-1 具有诸如 gensym 之类的卫生性,以及 Scheme 中一系列令人困惑的类似于语法结构的宏,这些宏可以保持卫生性。

据我所知,这个问题主要是一个稻草人的论点:这只是较差或较旧的实现中的问题。

Clojure 通过 gensym 或读取器宏 myvar# 提供卫生宏(# 本质上是 gensym)。

而且您也不必担心本地作用域在宏中重新绑定函数:Clojure 都是干净的:

user=> (defmacro rev [xs] `(reverse ~xs))
#'user/rev
user=> (rev [1 2 3])
(3 2 1)
user=> (let [reverse sort] (rev [1 2 5 3 6]))
(6 3 5 2 1)

这里有一些变量卫生:

user=> (defmacro k [] (let [x# "n"] x#))
#'user/k
user=> (k)
"n"
user=> (let [x "l"] (k))
"n"
user=> (let [x "l"] (str (k) x))
"nl"

注意我们性感的 gensym'd x#.

Lisp-2 means you have two namespaces: one for functions, one for the other stuff.

This means you're less likely to rebind a function value (or var value) in a macro, unwittingly.

In Lisp-1, since there's one namespace, you're (statistically, but not practically) twice as likely to hit an existing definition.

In reality, Lisp-1s have hygiene covered with things like gensym and Scheme's confusingly wide array of syntax-structure-like macros that keep things hygienic.

As best I can tell, the issue is mostly a straw-man argument: it's only an issue in the poorer or older implementations.

Clojure offers hygienic macros through gensym or the reader macro myvar# (the # is essentially gensym).

And you don't have to worry about local scope rebinding your function in your macros, either: Clojure is all clean:

user=> (defmacro rev [xs] `(reverse ~xs))
#'user/rev
user=> (rev [1 2 3])
(3 2 1)
user=> (let [reverse sort] (rev [1 2 5 3 6]))
(6 3 5 2 1)

And here's some variable hygiene:

user=> (defmacro k [] (let [x# "n"] x#))
#'user/k
user=> (k)
"n"
user=> (let [x "l"] (k))
"n"
user=> (let [x "l"] (str (k) x))
"nl"

Notice our sexy gensym'd x#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文