宏观定义中的“位置太少”

2024-01-04

我正在尝试创建一些以这种方式使用(实验)宏的示例:

use experimental :macros;
macro cards_vars() { 
  (<hearts clubs diamonds spades> X~ 1..10).map: { "my \$$^x = False;" }  
};
cards_vars(); 
say $hearts1;

这将创建并运行宏,然后检查定义的变量之一是否存在。但我收到这个错误:

Too few positionals passed; expected 3 arguments but got 2

我什至不知道这个错误来自哪里。我认为它在 cards_vars() 中,但我不知道是否是这样。声明不带括号的宏会产生相同的错误。


Update:需要明确的是,宏不仅是实验性的,而且非常初级且有缺陷。有关此内容的更多信息,请参阅莫里茨对另一个宏问题的回答 https://stackoverflow.com/a/53902789/1077672.


让我们从代码开始:

use experimental :macros;
macro foo { 42 }
foo

这产生相同的编译时 error:

Too few positionals passed; expected 3 arguments but got 2

You get this error if you return anything other than an AST https://docs.perl6.org/type/AST object from a macro.1 Which is reasonable given that this is the entire point of the macro construct. The error message is less than awesome -- but then again macros are an experimental feature.


所以你需要返回一个 AST。这是一种方法:

use experimental :macros;
macro foo { AST.new }
foo

这产生了run-time error:

Useless use of constant value foo in sink context (line 3)

这表明宏已经完成了它的工作。编译器已完成编译并进入运行时。


明确返回AST对象是错误的处理方式。第一个原因是在AST文档页面:

目前还没有为 AST 定义 API。希望这将成为宏的工作 https://github.com/masak/007.

The second reason is that there's a higher level construct for constructing AST objects, namely the quasi { ... } construct3 mentioned on the doc page and by Scimon:

use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42

The quasiblock 告诉编译器将所包含的语句编译为 AST 形式。

请注意,结果不是与块对应的 AST。上面它是一个 AST 对象,对应于42.


所以,最后,回到你想要做的事情。

简化:

use experimental :macros;
macro foo { quasi { my $bar } }
foo;
say $bar

yields:

Error while compiling ... Variable '$bar' is not declared

Whereas:

use experimental :macros;
macro foo { quasi { class bar {} } }
foo;
say bar; # (bar)

因此,最重要的是,词法声明目前无法坚持下去。

实验还没有进行到这一步。

Carl Mäsak,Rakudo 中实验宏的创建者,正在继续进行该实验007 https://github.com/masak/007。如果您在 GH 存储库中留下问题,Carl 将会答复。


1 When the compiler encounters a call to a routine that it knows is a macro2 it replaces the macro call with its result. In more detail the compiler:

  • 将宏的所有参数编译为 AST 形式;

  • 调用宏(在编译时),以 AST 形式传递参数;

  • 运行预计返回 AST 对象的宏例程(呃,"ASTish" https://stackoverflow.com/a/53904138/1077672);

  • 将生成的 AST(ish) 对象拼接到正在构建的整体 AST 中。

如果您不返回 AST(ish) 对象,那么最后一步就会出错,并出现标题中的错误消息。

2 Currently, if you put the macro definition after the call then the compiler doesn't realize it's a macro and treats it as an ordinary routine:

use experimental :macros;
say foo; # 42
macro foo { 42 }
say bar; # AST.new
macro bar { quasi { 42 } }
say bar; # 42

如果这会导致编译时错误,那可能会更好。

3 Carl, the macros champion, likes the word quasi. It draws from lisp heritage which draws from mathematics heritage. Imo it is a "too cute" choice that's a less than awesome fit for P6. My rationale is that Perl philosophy suggests choice of keywords with familiar meaning to newbies. The word "quasi" has a well known normal English connotation of meaning "sort of, but not really". That's not at all helpful. (I have suggested toAST to Carl but he prefers quasi.)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

宏观定义中的“位置太少” 的相关文章

  • 在 macOS 上运行 Comma IDE 时找不到匹配的虚拟机

    我安装了 Comma IDEthis https commaide com download链接 但当我尝试通过双击应用程序文件夹中 Finder 中的应用程序图标来运行它时 出现错误 未找到匹配的 VM 需要 Java 1 8 或更高版本
  • 用宏包装函数(无需重命名)C

    我有兴趣通过包装现有函数调用来添加一些额外的逻辑without重命名它们 仅供测试 我发现的现有解决方案依赖于将函数包装在不同名称的宏中 这可能意味着更改大量代码 有什么建议么 请注意 我知道LD PRELOAD 但我有兴趣使用宏来检查传递
  • 如何运行 Abaqus 宏 (.py) 脚本

    我是Python新手 我使用 Abaqus 宏管理器生成了一个宏 它是一个 py 脚本 我意识到该脚本仅在从 Abaqus 管理器运行时才有效 并且不能自行运行 请有人知道如何修改这个脚本 以便我可以在不使用 Abaqus 的情况下运行它
  • 如何驯服 Windows 标头(有用的定义)?

    在其中一个答案中this https stackoverflow com questions 1394132 macro and member function conflict问题jalf https stackoverflow com
  • 如何调用使用 Define 创建的 GNU make 宏?

    在我的 Makefile 中调用 GREP 的两种方式有什么区别吗 我有什么理由应该使用其中之一 两者似乎产生相同的结果 define GREP word 3 shell echo define FOO 0xfff00100 endef a
  • raku 可以避免这个 Malformed UTF-8 错误吗?

    当我运行这个 raku 脚本时 my proc run tree du out proc out slurp close say 我在 MacOS 上遇到此错误 Malformed UTF 8 near bytes ef b9 5c 而不是
  • Clojure 宏expand

    Why does macroexpand arm getHand getFinger 扩展到 arm getHand getFinger while macroexpand gt arm getHand getFinger 扩展到 getF
  • 如何在宏中允许可选的尾随逗号?

    这是我想要的综合示例 macro rules define enum Name ident Variant ident gt pub enum Name None Variant define enum Foo A B 这段代码可以编译 但
  • 宏内调用函数和宏的区别?

    我的难题是以下示例 defmacro macro1 x println x defn func1 x println x defmacro macro2 x macro1 x func1 x defmacro macro3 x func1
  • 使用 Scala 宏或反射实例化类

    在我的 scala 代码中 我希望能够实例化一个新类 例如 假设我有以下代码 class Foo def foo 10 trait Bar val bar 20 理想情况下 我希望能够做类似的事情 def newInstance A lt
  • 用于将具有相同前缀的所有变量的值相加的 SPSS 语法

    我想知道是否有一种方法可以让 SPSS 将具有相同前缀的所有变量相加 例如 我有名为MFQAP 1 MFQAP 2 MFQAP 3等等 有没有办法告诉SPSS将所有以以下开头的变量相加MFQAP 我知道我可以告诉 SPSS 将所有变量相加M
  • 使用 __LINE__ 获取代码行

    我尝试使用以下方法打印当前代码的行号 include
  • Common Lisp 反引号/反引号:如何使用?

    我在使用 Lisp 的反引号读取宏时遇到问题 每当我尝试编写一个似乎需要使用嵌入式反引号的宏时 例如 w x y 来自保罗 格雷厄姆的ANSI 通用 Lisp 第 399 页 我不知道如何以编译的方式编写代码 通常 我的代码会收到一整串错误
  • 最好的 AutoHotKey 宏? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 用于嵌套表达式的方案宏

    可以在Scheme中编写宏吗 用define syntax 例如 将采用如下表达式 op a b c d e f g h i j 并将像这样的yield表达式作为输出 op op op op op op op op op a b c d e
  • Clojure 中的宏和函数

    我在这个 Clojure 教程中读到了以下行 http java ociweb com mark clojure article html Macros http java ociweb com mark clojure article h
  • 如何重写 NQPMatch.Str 函数

    或者如何改变
  • 在 Perl 6 中将正则表达式作为参数传递

    的延续这个问题 https stackoverflow com q 47218587 7730888 而且可能是一个更奇怪的 我可以例如连接两个regexes用一个sub 当然 我明白 如何用regex 下面的代码是完全错误的 但我希望它能
  • 什么是具有副作用的表达式?为什么不应将它们传递给宏?

    我在 C 如何编程 一书中看到这样一句话 具有副作用 即变量值被修改 的表达式不应传递给宏 因为宏参数可能会被多次求值 我的问题是什么是具有副作用的表达式以及为什么不应将它们传递给宏 经典的例子是计算两个值的最大值的宏 define MAX
  • Clojure 宏总是泄漏吗?

    如果你读过这个问题宏 gt 带有匿名函数 https stackoverflow com questions 10740265 macro with anonymous functions 10740411 comment13981517

随机推荐