问题标签 [hygiene]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
351 浏览

rust - 如何使用 proc 宏来创建可能违反卫生的宏?

我正在尝试创建一个名为derive_pattern 的简单库。我的最终目标是能够写出这样的东西:

我很好奇这是否可能。到目前为止,我的尝试都失败了。在定义程序宏时,可以控制标识符的范围以绕过卫生,但据我所知,程序宏无法定义新的程序宏。因此,我的程序宏必须生成 macro_rules 宏,而这些宏最终会强制执行卫生。

这是我的程序宏定义:

我已将带有完整 Cargo.toml 等的版本上传到 github:https ://github.com/jgarvin/derive_pattern

我得到的错误是在测试中的第一个断言上:

0 投票
1 回答
200 浏览

rust - 如何关闭宏观卫生?

我正在尝试制作一个粘贴在样板代码中的宏,然后我想使用它粘贴的变量。Rust 的宏观卫生正在防止这种情况发生;我该如何关闭它?

我知道有一些方法可以解决它,通过将所有变量传递给宏,但这会使宏无用......我发现了一个名为 unhygienic 的箱子,它说它就是这样做的,但我无法得到它工作。

这就是它应该如何工作的方式。这是您可以在 Java 或 JavaScript 中使用处理(绘图/图形框架)的方式(这将显示一辆移动的汽车(在一个Car类中定义)和一个矩形:

setup是你在主循环之前所做的draw一切,也是你在循环内所做的一切。这就是我希望它在 Rust 中的样子(绝对不需要,只是为了美观):

0 投票
1 回答
97 浏览

macros - 如何从输入模式中插入文字标识符作为语法规则宏中的符号

我有这样的代码:

代码正在工作,它通过用 lambda 包装宏作为值。我的问题是如何将语法规则宏文字符号放入其中,'name而不是(cons 'lambda ...)输出代码为:

所以它可以使用这样的代码:

它打印所有的数字。

我知道我可以将模式中的名称更改为其他名称,但我想了解更多关于语法规则及其边缘情况的信息。那么,如果我将其用作输入模式,是否可以有名称?

我正在寻找 R7RS 的答案,它涵盖了更多此类边缘情况。

0 投票
2 回答
296 浏览

rust - 在 Rust“macro_rules”宏中的调用站点使用本地绑定

考虑以下代码段:

如果我编译它,我会得到:

但是不应该将quick_hello调用main扩展为包含该let h = "hello"语句的块,从而允许我在调用站点将其用作“hello”的速记吗?

我可能会知道这样做是为了保持宏的卫生,但是如果我需要上述行为怎么办?有没有办法“关闭”卫生来实现这一目标?

0 投票
0 回答
28 浏览

build - Gitlab CI 中卫生的树外构建

为了强制构建卫生,如果 Gitlab CI 修改了它的源目录,我希望它将构建标记为失败。执行此操作的常用方法是在源以只读方式挂载的容器中运行构建,这样任何写入源目录的尝试都会失败。

我们还远未准备好强制执行卫生构建,但即使是朝这个方向迈出的最初几步,Gitlab 也让我感到有些意外。目前,源在 $CI_PROJECT_DIR 中签出,工件需要在 $CI_PROJECT_DIR 中生成,并且设置 $CI_PROJECT_DIR 甚至不被尊重

解决这个问题的最好方法是移动东西吗?

0 投票
2 回答
49 浏览

macros - 如何使用 Scheme 中的语法规则从 List 创建 Alist?

就像我想改变的练习一样:

进入

这可能与语法规则吗?

我的尝试:

它扩展成的问题:

语法规则可以使用宏 alist 吗?它应该是什么样子?

编辑:

又一次尝试

它返回(("foo" . 2) (("bar" . 4) ("baz" . 6)))

0 投票
1 回答
130 浏览

rust - `quote`宏是如何实现插值的?

quote(声明性)和proc_quote(过程性)宏如何允许对局部变量进行插值?

由于(声明性)宏是卫生的,我希望它们无法访问它们被调用的环境。

0 投票
0 回答
198 浏览

debugging - 如何调试 Julia 宏?

注意:这个问题是指 Julia v1.6。当然,在任何时候,理想情况下,答案也应该回答最新版本的问题。

在 Julia 中似乎存在很多关于宏观卫生的问题和困惑。$name虽然我阅读了相关的手册页,但在使用插值 ( )quote和其他引用语法、宏和作用于表达式的函数之间的行为差​​异等内容时,我仍然很难编写宏esc

Julia 提供了哪些工具来查找宏中的错误以及如何有效地使用它们?

这当然是一个广泛的问题,我认为非常值得一个专门的手册页,而不是当前在元编程概述中的事后思考。尽管如此,我认为可以通过考虑和调试一个具体的例子来有效地回答它(即,以一种教我和其他人很多关于主要、一般性问题的方式)。因此,我将讨论一个简单的

玩具示例宏:

(请注意,宏Base.@locals “构造[s] 名称(作为符号)和定义为调用站点的所有局部变量的值的字典”[来自文档字符串]。)

一些代码来测试这个

假装你不明白为什么会发生错误。我们如何知道发生了什么?

调试技术(我知道)包括:

  • @macroexpand (expr): 展开里面的所有宏(expr)
  • @macroexpand1 (expr): 只展开最外层的宏(expr),通常只是你正在调试的宏。很有用,例如,如果您正在调试的宏返回带有@warn内部的表达式,而您不希望看到扩展。
  • macroexpand(m::Module, x; recursive=true): 结合以上两者并允许指定“调用者”模块
  • dump(arg): 可以在宏内部使用来检查它的参数arg
  • eval(expr): 评估表达式(几乎不应该在宏体内使用)。

请帮助将有用的东西添加到此列表中。

使用dump表明print_local有问题的(即最后一次)宏调用期间的参数是 a Symbol,准确地说,它的值是:var_false

让我们看一下宏返回的表达式。例如,这可以通过将最后一个宏调用 ( MyModule.@mac var_false)替换为 来完成return (@macroexpand1 MyModule.@mac var_false)。结果:

我们可以手动删除烦人的评论(肯定有内置的方法可以做到这一点?)。

在这个简单的例子中,这里列出的调试工具足以看出问题所在。我们注意到if宏的返回表达式中的语句将内插符号“重新定义”到宏的父模块:它查看Main.MyModule.var_false. 我们打算让它Main.var_false在调用者范围内。

可以通过替换来解决这个if $print_local问题if $(esc(print_local))。在这种情况下,宏观卫生将print_local单独保留变量的内容。esc对于插入表达式的顺序和位置以及$插入表达式,我仍然有些困惑。

假设我们搞砸了改写if $esc(print_local),因此将esc函数插入到表达式中,而不是转义任何东西(类似的错误让我很头疼)。这导致返回的表达式(通过获得@macroexpand1)无法通过执行执行eval,因为该esc函数在宏之外很奇怪,返回类似:($(Expr(:escape, <somthing>))). 事实上,我通常对Expr通过获得的 essions何时@macroexpand真正可执行(与宏调用具有相同的效果)以及如何执行它们(eval并不总是有效)感到困惑。对此有什么想法吗?

0 投票
1 回答
71 浏览

macros - Racket - 如何定义一个可以在语法转换器和普通代码中使用的函数?

我正在使用语法转换器在 Racket 中定义宏。我想创建一些辅助函数来帮助我操作语法。但是,我在语法转换器之外定义的函数在语法转换器内部是不可用的。例如,在下面的代码中

我收到错误“my-function: reference to an unbound identifier at phase: 1; the transformer environment”。

经过一番搜索,我能够编写以下代码,以便my-function在语法转换器中可用。

但问题是,my-function这次在语法转换器之外不可用。有时我想在普通代码中检查那些辅助函数,所以我需要能够从语法转换器的内部和外部调用它,就像函数一样cadr。我怎样才能做到这一点?

我知道我的问题与 Racket 的语法模型有关,特别是“阶段级别”的概念,但我从来没有真正理解它。如果您能提供一些易于理解的教程来解释它,我将更加感激。

0 投票
3 回答
117 浏览

elixir - 长生不老药!...如何从调用者的范围内读取变量

对不起,如果这已经被问到了。在论坛中搜索var!给了我所有带有 word 的帖子var。很难缩小范围。

努力编写一个宏,该宏从调用者的上下文中读取一个变量并从函数中返回它。这是我能想到的最简单的问题形式:

目标是在我运行 iex 会话时看到这一点:

但这不会编译。来电者my_var也未使用。

编译错误expected "my_var" to expand to an existing variable or be part of a match.

我已经阅读了 McCord 的元编程书、这篇博文 ( https://www.theerlangelist.com/article/macros_6 ) 以及许多其他内容。似乎它应该工作,但我只是不知道为什么它不会..