如何将文件的内容作为宏的参数包含在内? [英] How can I include the contents of a file as an argument to a macro?

查看:58
本文介绍了如何将文件的内容作为宏的参数包含在内?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现处理的Lisp版本,为此,我采用了<一个href ="https://crates.io/crates/macro_lisp" rel ="nofollow noreferrer"> macro_lisp 条板箱,可在编译时将Lisp代码转换为Rust.

I'm trying to implement a Lisp version of Processing, and to that end I'm employing the macro_lisp crate to turn Lisp code into Rust at compile time.

当我按如下方式构建代码时,它可以工作:

It works when I structure my code like so:

main.rs

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

hello.lisp

lisp!(println "hello")

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

Note that I have to wrap the content of hello.lisp in lisp!(), in hello.lisp itself.

我希望它的结构如下:

main.rs

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

hello.lisp

println "hello"

但这给了我以下错误:

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

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

There should not be an EOF there, there should be hello "list".

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

What am I doing wrong? Do I need to patch macro_lisp?

推荐答案

不幸的是,您想要的东西并不容易实现.

Unfortunately, what you want is not easy to achieve.

宏的功能与功能明显不同.该问题的重要部分是嵌套宏调用"是从外部到内部" 求值的(与函数不同,函数首先对参数求值,因此从内部到外部").我们可以通过这个小程序看到效果:

Macros work significantly different than functions. The important part for this question is that "nested macro calls" are evaluated from "outside to inside" (unlike functions, where arguments are evaluated first, so "inside to outside"). We can see that in effect with this tiny program:

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

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

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

您会看到游乐场,它显示ident ! ().这意味着在评估foo!之前未评估bar!()宏. (此外,编译器甚至会警告未使用的宏定义bar.)

As you can see on the Playground, it prints ident ! (). That means the bar!() macro was not evaluated before foo! was evaluated. (Furthermore, the compiler even warns about the unused macro definition bar.)

include!也不例外,因此我们不能将其用作其他宏的参数.那么可以怎么做呢?我可以想到两种方式,这两种方式都不是特别容易或优雅的:

include! is no exception to this, so we can't use it as an argument to other macros. So how can you do it? I can think of two ways, neither of which is particularly easy or elegant:

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

  • Write a procedural macro that loads the file and emits the token stream lisp! { ... } where ... is the file content. It could be tricky to get all the paths right (and to make sure everything is correctly recompiled when the lisp file changes), but it should in theory work.

使用构建脚本将源代码中的include!("*.lisp")字符串手动替换为文件内容.显然,您实际上并不想修改实际的源代码(已签入git),但必须对此稍加巧妙.一些箱子使用这种策略,但仅出于非常特殊的原因.我不建议您这样做.

Use a build script to manually replace include!("*.lisp") strings in your source code with the file content. Obviously, you don't actually want to modify your real source code (that is checked into git), but have to be a bit clever about it. A few crates use such a tactic, but only for very special reasons. I wouldn't advise to do this in your case.

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

In your case, I would think twice whether using a lot of LISP code in Rust is a good idea, because there aren't any nice ways to make it work (as far as I can see).

这篇关于如何将文件的内容作为宏的参数包含在内?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆