gpt4 book ai didi

macros - 如何将文件的内容作为参数包含在宏中?

转载 作者:行者123 更新时间:2023-11-29 07:54:10 24 4
gpt4 key购买 nike

我正在尝试实现 Processing 的 Lisp 版本,为此我正在使用 macro_lisp crate 在编译时将 Lisp 代码转换为 Rust。

当我像这样构建我的代码时,它会起作用:

ma​​in.rs

fn main() {
include!("hello.lisp");
}

你好.lisp

lisp!(println "hello")

请注意,我必须将 hello.lisp 的内容包装在 lisp!() 中,在 hello.lisp 本身中。

我希望它的结构如下:

ma​​in.rs

fn main() {
lisp!(include!("hello.lisp"));
}

你好.lisp

println "hello"

但这给了我以下错误:

error: expected expression, found `<eof>`
--> src/main.rs:47:18
|
47 | lisp!(include!("draw.lisp"));
| ^ expected expression

那里不应该有 EOF,应该有 hello "list"

我做错了什么?我需要修补 macro_lisp 吗?

最佳答案

不幸的是,你想要的并不容易实现。

宏的工作原理与函数有很大不同。这个问题的重要部分是“嵌套宏调用”是从“外到内”计算的(不像函数,参数首先被计算,所以“从内到外”)。我们可以通过这个小程序看到效果:

macro_rules! foo {
($x:literal) => { "literal" };
($x:ident ! ()) => { "ident ! ()" };
}

macro_rules! bar {
() => { 3 };
}

fn main() {
let s = foo!(bar!());
println!("{}", s);
}

如你所见on the Playground , 它打印 ident ! ()。这意味着 bar!() 宏在 foo! 被求值之前没有被求值。 (此外,编译器甚至会警告未使用的宏定义 bar。)

include! 也不异常(exception),因此我们不能将它用作其他宏的参数。那么可以怎么做呢?我可以想到两种方法,这两种方法都不是特别简单或优雅:

  • 编写一个加载文件并发出 token 流的过程宏 lisp! { ... } 其中 ... 是文件内容。正确设置所有路径(并确保在 lisp 文件更改时正确重新编译所有内容)可能很棘手,但理论上应该可行。

  • 使用构建脚本手动将源代码中的 include!("*.lisp") 字符串替换为文件内容。显然,您实际上并不想修改您的真实源代码(已 checkin git),但必须对此有所了解。一些 crate 使用这种策略,但只是出于非常特殊的原因。我不建议您这样做。

在你的情况下,我会三思而后行是否在 Rust 中使用大量 LISP 代码是个好主意,因为没有任何好的方法可以让它工作(据我所知)。

关于macros - 如何将文件的内容作为参数包含在宏中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54429958/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com