为孩子优先的懒惰评估器设计数据结构,打印过程

时间:2016-12-12 02:11:10

标签: rust lazy-evaluation

我正在使用编译器插件构建一个惰性表达式求值程序like Python's

我想打印一个日志:

assert ( left == vec![1, 2, 3, 4] )
assert ( vec![1, 2, 3, 4] == vec![1, 2, 3, 4] );

并尝试:

// crate rt
pub struct Expr<T, F: FnMut() -> T> {
    // I noticed that this must be changed to fn with format!() call, to
    // support updating child.
    src: &'static str, // holds value
}
pub trait EvalTo: Display {
    /// Type of expression
    type Type;

    /// Returns Some(val) when done
    /// Accepts &mut self as it might be called many time.
    fn eval_one_level(&mut self) -> Some<T>;
}

impl<T, F> EvalTo for Expr<T, F> {
    type Type = T;
}
/// Prints source before evaluation, (it must be changed)
/// and value after evaluation.
impl<T, F> Display for Expr<T, F> {}

使用编译器插件在编译时创建它们。但是当我做的时候

let left = vec![1, 2, 3, 4];
lazy_expr!(left == vec![1, 2, 3, 4]);

它扩展到

::rt::binary({
   ::rt::Expr::wrap(::rt::Source{ expr: "left" }, || Some(left))
}, { 
   ::rt::Expr::wrap(::rt::Source{ expr: "vec!(1, 2, 3, 4)" },
   || vec![1, 2, 3, 4])
}).eq()

并且编译器不喜欢它。它说cannot move out of captured outer variable in an `FnMut` closure

所以我不能使用FnMut,但需要多次调用它,并且需要能够修改子表达式。

是否存在允许捕获局部变量的数据结构,但是可以使用&mut self多次调用?我应该使用FnOnce(&mut Context)吗?

1 个答案:

答案 0 :(得分:0)

我不再需要这个,因为我使用了另一个apporach。但为了完成,您可以使用(&mut self)定义特征并使用 [std::mem::replace] []获取自有值,Option有一个名为.take()的辅助方法。

对于谁想要使用编译器插件构建延迟可评估引擎,我did some more on compile time

它叫

fn capture<T :?Sized>(&mut self, expr: &'static str, val: &T)

来自生成的代码,如

ctx.capture("f()", &_var_of_expr)

因此上下文可以用它来表达表达式和值。