2013-05-25 23 views
0

我試圖捆綁狀態的結構與變異狀態回調在一起。獨特的指針狀態+回調拉斯特

struct StateAndCallbacks01 { 
    state: @mut int, 
    inc: @fn(), 
    dec: @fn() 
} 

let state01: @mut int = @mut 0; 
let inc01: @fn() = || { 
    *state01 += 1; 
}; 
let dec01: @fn() = || { 
    *state01 -= 1; 
}; 
let state_cbs_01 = @StateAndCallbacks01 { 
    state: state01, 
    inc: inc01, 
    dec: dec01 
}; 
(state_cbs_01.inc)(); 
println(fmt!("state: %d", *state_cbs_01.state)); 
(state_cbs_01.dec)(); 
println(fmt!("state: %d", *state_cbs_01.state)); 

接下來,我想這種結構發送到另一個工作,因而不得不到處切換到獨特的指針:當我使用管理指針,它工作正常。我無法使這項工作:「錯誤:過時的語法:const或可變擁有指針」

struct StateAndCallbacks02 { 
    state: ~mut int, 
    inc: ~fn(), 
    dec: ~fn() 
} 

let state02: ~mut int = ~mut 0; 
let inc02: ~fn() = || { 
    *state02 += 1; 
}; 
let dec02: ~fn() = || { 
    *state02 -= 1; 
}; 
let state_cbs_02 = ~StateAndCallbacks02 { 
    state: state02, 
    inc: inc02, 
    dec: dec02 
}; 

let (port, chan): (Port<bool>, Chan<bool>) = stream(); 
do spawn { 
    (state_cbs_02.inc)(); 
    println(fmt!("state: %d", *state_cbs_02.state)); 
    (state_cbs_02.dec)(); 
    println(fmt!("state: %d", *state_cbs_02.state)); 
    chan.send(true); 
}; 
let result = port.recv(); 
println(fmt!("result: %s", result)); 

有什麼建議?任何更好的方法來跨任務發送回調?

回答

3

而是在結構保持功能的字段,你可以方法,而不是添加到該結構的。

struct Foo { 
    data: int 
} 

impl Foo { 
    fn inc(&mut self) { 
     self.data += 1; 
    } 
} 

impl語法可讓您在結構上定義方法。你可以再打:

let mut my_foo = Foo { data: 0 }; 
my_foo.inc(); 

您必須聲明my_foo爲可變的,因爲inc方法需要佔用一個可變引用。

的原因過時的語法錯誤,是因爲這樣做~mut 0因爲可變性由誰「擁有」的對象決定棄用。你必須做的是let mut foo = ~0。變量foo是'所有者',因此是您聲明可變性的地方。 @-指針是特殊的,它們不會繼承可變性,並由任務本地GC進行管理。 (節的 9更好地解釋這一點)

因此,與所有的放在一起,你可以寫你的原來的代碼如下所示:

struct State { 
    data: int 
} 

impl State { 
    fn inc(&mut self) { 
     self.data += 1; 
    } 

    fn dec(&mut self) { 
     self.data -= 1; 
    } 
} 

fn main() { 

    let state = State { 
     data: 0 
    }; 

    let (port, chan) = stream(); 

    do spawn { 

     let mut state = state; 

     state.inc(); 
     println(fmt!("State: %d", state.data)); 
     state.dec(); 
     println(fmt!("State: %d", state.data)); 

     chan.send(true); 
    }; 

    let result = port.recv(); 
    println(fmt!("Result: %?", result)); 

} 
+0

平原'impl'解決方案僅如果只能「inc」和「dec」的一個可能值;如果這些功能依賴於數據,即使用特性或只使用在結構的國有關閉(沒有'〜mut'的'mut')改變會更好。 – huon

+0

我忽略提及,但我真的需要inc/dec的多個實現。這是我與XML SAX事件處理有問題的簡化版本,而不是增/減我會START_ELEMENT/END_ELEMENT /文本。試圖做一些類似的東西添加。 設狀態=〜國家{...,得到一個「錯誤:移出捕獲外層變量的堆封閉」。做你確實做了什麼工作。我真的不明白爲什麼一個擁有的指針不能傳遞給任務,但是棧引用起作用。 –