如何将从配置文件加载的参数传递给过程宏函数?
How to pass parameters loaded from configuration file to a procedural macro function?
这是我正在尝试解决的问题。我有多个生成预计算值表的过程宏函数。目前,我的程序宏函数采用文字整数形式的参数。我希望能够从配置文件传递这些参数。我可以重写我的函数以从宏本身加载参数。但是,我想保留顶级板条箱的配置,如本例所示:
top-level-crate/
config/
params.yaml
macro1-crate/
macro2-crate/
因为宏函数的输入是语法标记而不是 运行 时间值,所以我无法从顶级包加载文件并传递参数。
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(500, 123, 499);
const TABLE2: [f32;100] = gen_table2!(1, 3);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
我希望能够从这样的配置文件中将参数传递给 gen_table1 和 gen_table2:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
// Load values PARAM1, PARAM2, PARAM3, PARAM4, PARAM5
const TABLE1: [f32;100] = gen_table1!(PARAM1, PARAM2, PARAM3);
const TABLE2: [f32;100] = gen_table2!(PARAM4, PARAM5);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
明显的问题是PARAM1、PARAM2、PARAM3、PARAM4、PARAM5是运行时间值,proc宏依赖构建时间信息生成表。
我正在考虑的一个选项是创建另一个 proc 宏,专门用于将配置加载到使用 quote!
标记构建的某种数据结构中。然后将其输入宏。然而,这感觉很老套,配置文件需要加载几次。 params 数据结构也需要跨宏紧密耦合。代码可能如下所示:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(myparams!());
const TABLE2: [f32;100] = gen_table2!(myparams!());
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
有什么改进或进一步的建议吗?
gen_table1!(myparams!());
不起作用:宏不会像函数调用那样从内向外扩展。您的 gen_table1
宏将接收文字标记流 myparams ! ()
并且无法计算此宏,因此无法访问 myparams
的“return 值”。
现在,我只看到一种真正的方法来做你想做的事:从 gen_table1
和 gen_table2
中的文件加载参数,然后只传递包含参数的文件的文件名.例如:
const TABLE1: [f32; 100] = gen_table1!("../config/params.yaml");
const TABLE2: [f32; 100] = gen_table2!("../config/params.yaml");
当然,这可能会导致这两个宏中出现重复代码。但这应该可以用通常的工具解决:提取参数加载到一个函数中(如果两个宏都在同一个 crate 中)或另一个实用程序 crate(如果两个宏在不同的 crate 中)。
你还一直提到“运行时间价值”这个词。我 认为 你的意思是“一个常量值,而不是文字”,你指的是这样的东西:
const PARAM1: u32 = load_param!();
const TABLE1: [f32; 100] = gen_table1!(PARAM1); // <-- this does not work as expected!
因为在这里,您的宏再次接收文字标记流 PARAM1
而不是所述参数的值。
所以是的,我认为这就是“运行时间价值”的意思。当然,我现在没有更好的术语,但是“运行时间值”是 misleading/wrong,因为该值在编译时可用。如果您谈论的是实际的 运行 时间值,即编译完成后仅在 运行 时间可知的值,那么您将无法执行您想要的操作。那是因为 proc 宏 运行 在编译时出现一次,而从不在 运行 时出现。
这是我正在尝试解决的问题。我有多个生成预计算值表的过程宏函数。目前,我的程序宏函数采用文字整数形式的参数。我希望能够从配置文件传递这些参数。我可以重写我的函数以从宏本身加载参数。但是,我想保留顶级板条箱的配置,如本例所示:
top-level-crate/
config/
params.yaml
macro1-crate/
macro2-crate/
因为宏函数的输入是语法标记而不是 运行 时间值,所以我无法从顶级包加载文件并传递参数。
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(500, 123, 499);
const TABLE2: [f32;100] = gen_table2!(1, 3);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
我希望能够从这样的配置文件中将参数传递给 gen_table1 和 gen_table2:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
// Load values PARAM1, PARAM2, PARAM3, PARAM4, PARAM5
const TABLE1: [f32;100] = gen_table1!(PARAM1, PARAM2, PARAM3);
const TABLE2: [f32;100] = gen_table2!(PARAM4, PARAM5);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
明显的问题是PARAM1、PARAM2、PARAM3、PARAM4、PARAM5是运行时间值,proc宏依赖构建时间信息生成表。
我正在考虑的一个选项是创建另一个 proc 宏,专门用于将配置加载到使用 quote!
标记构建的某种数据结构中。然后将其输入宏。然而,这感觉很老套,配置文件需要加载几次。 params 数据结构也需要跨宏紧密耦合。代码可能如下所示:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(myparams!());
const TABLE2: [f32;100] = gen_table2!(myparams!());
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
有什么改进或进一步的建议吗?
gen_table1!(myparams!());
不起作用:宏不会像函数调用那样从内向外扩展。您的 gen_table1
宏将接收文字标记流 myparams ! ()
并且无法计算此宏,因此无法访问 myparams
的“return 值”。
现在,我只看到一种真正的方法来做你想做的事:从 gen_table1
和 gen_table2
中的文件加载参数,然后只传递包含参数的文件的文件名.例如:
const TABLE1: [f32; 100] = gen_table1!("../config/params.yaml");
const TABLE2: [f32; 100] = gen_table2!("../config/params.yaml");
当然,这可能会导致这两个宏中出现重复代码。但这应该可以用通常的工具解决:提取参数加载到一个函数中(如果两个宏都在同一个 crate 中)或另一个实用程序 crate(如果两个宏在不同的 crate 中)。
你还一直提到“运行时间价值”这个词。我 认为 你的意思是“一个常量值,而不是文字”,你指的是这样的东西:
const PARAM1: u32 = load_param!();
const TABLE1: [f32; 100] = gen_table1!(PARAM1); // <-- this does not work as expected!
因为在这里,您的宏再次接收文字标记流 PARAM1
而不是所述参数的值。
所以是的,我认为这就是“运行时间价值”的意思。当然,我现在没有更好的术语,但是“运行时间值”是 misleading/wrong,因为该值在编译时可用。如果您谈论的是实际的 运行 时间值,即编译完成后仅在 运行 时间可知的值,那么您将无法执行您想要的操作。那是因为 proc 宏 运行 在编译时出现一次,而从不在 运行 时出现。