如何在Rust中动态构建具有不同数量参数的函数调用? [英] How to dynamically build function calls with different numbers of arguments in Rust?
问题描述
如何获取函数自变量AST变体的向量,提取值并使用它们实例化函数调用?
How do I take a vector of function argument AST variants, extract the values, and use them to instantiate a function call?
我正在写一个评估某些表达式的解释器.一些表达式是函数调用.我很难弄清楚如何将AST转换为实际调用.AST给了我函数名和参数向量.我可以使用映射查找要从名称调用的函数指针,但是将参数传递给函数指针是有问题的.
I am writing an interpreter that evaluates certain expressions. Some of the expressions are function calls. I am having a hard time figuring out how to translate the function calls AST to the actual call. The AST gives me the function name and a vector of arguments. I can lookup the function pointer to call from the name using a map, but passing the arguments to the function pointer is problem.
Rust没有splat运算符(参数扩展).我可以将它们作为元组传递并使用参数的解构,但是我不知道如何将AST参数枚举变量的向量转换为具体类型的元组.
Rust does not have a splat operator (argument expansion). I could pass them as a tuple and use destructuring of the arguments, but I can't figure out how to convert the vector of AST argument enum variants to a tuple of the concrete types.
我不能简单地映射或循环AST参数以提取值并生成元组.
I can't simply map or loop over the AST arguments to extract the values and produce a tuple.
我可以使用嵌套元组来逐步构建异构列表:
I can use nested tuples to build a heterogenous list incrementally:
fn prepend<I,T>(i: I, t: T) -> (I,T) { (i, t) }
fn foo() {
let x = ();
let x = prepend(1, x);
let x = prepend(2.0, x);
let x = prepend(true, x);
}
但这只能起作用,因为 x
会被遮盖并且新的绑定具有不同的类型.这是行不通的:
But that only works because x
gets shadowed and the new binding has a different type. This won't work:
fn foo() {
let mut x = ();
x = prepend(1, x);
x = prepend(2.0, x);
x = prepend(true, x);
}
有什么想法吗?
推荐答案
您没有.Rust是一种静态类型的语言,您正尝试执行非静态确定的操作.
You don't. Rust is a statically typed language and you are attempting to do non-statically-determinable actions.
相反,您的所有函数都需要接收一组参数,验证是否有正确数量的参数(以及类型,如果适用于您的解释器),然后使用固定数量的参数调用适当的Rust函数:
Instead, all of your functions need to take in a collection of arguments, verify that there is the right number of arguments (and type, if appropriate to your interpreter), then call the appropriate Rust function with a fixed number of arguments:
// All of the panicking can be replaced by proper error handling.
enum Arg {
Bool(bool),
Int(i32),
}
impl Arg {
fn into_bool(self) -> bool {
match self {
Arg::Bool(b) => b,
_ => panic!("Not a bool"),
}
}
fn into_int(self) -> i32 {
match self {
Arg::Int(i) => i,
_ => panic!("Not an int"),
}
}
}
fn some_fn_wrapper(mut args: Vec<Arg>) {
assert_eq!(args.len(), 3);
let c = args.pop().unwrap();
let b = args.pop().unwrap();
let a = args.pop().unwrap();
some_fn(a.into_bool(), b.into_int(), c.into_bool())
}
fn some_fn(_a: bool, _b: i32, _c: bool) {}
所有这些都将在运行时发生,因为您要创建一种高度动态的语言.
All of this will happen at runtime, as you want to create a highly dynamic language.
另请参阅:
- 如何将切片的每个元素作为单独的参数传递给可变参数C函数?
- 如何将动态数量的类型化参数传递给函数?
- 调用仅在运行时已知的函数
- 如何创建具有可变数量的参数的函数?
- 在Rust中是否可以进行反射,如果可以的话,如何使用一些参数调用未知函数?
这篇关于如何在Rust中动态构建具有不同数量参数的函数调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!