2016-12-12 15 views
1

我正在使用編譯器插件構建一個懶惰表達式評估程序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)嗎?

+0

請製作[MCVE]。有人不太可能會創建一個編譯器插件來嘗試重現錯誤。理想情況下,做一些可以[在操場上運行](https://play.rust-lang.org/)。更好的是,[用相同的錯誤信息**回顧** 7個其他問題](http://stackoverflow.com/search?q=cannot+move+out+of+captured+outer+variable+in+an+ FnMut +閉包+是%3Aq)*之前*問。然後,解釋爲什麼*這個問題*與那些問題*不同。 – Shepmaster

+0

我決定做一些像http://pybites.blogspot.kr/2011/07/behind-scenes-of-pytests-new-assertion.html,因爲我不能用泛型來表示ast,這個問題對我來說變得毫無用處。 – kdy

+0

@Shepmaster這是關於設計的問題,而這些問題都是關於使用FnMut的。我並沒有試圖將價值轉移到收尾。相反,我想做一些事情,比如允許FnOnce和FnMut。我發現這可以通過[futures-rs]完成(http://alexcrichton.com/futures-rs/futures/index.html) – kdy

回答

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) 

所以上下文可以寫表達和值與它。