> This is similar to IO Monad in Haskell. Adding that to previously pure
> computational code is painful, but on the other hand it does emphasis
> that computational code != IO code and minimizing mixing between two
> typically leads to better design overall.
Yes, but you can have the compiler automatically transform normal code into the
equivalent of Haskell's "do notation", which is what C# does with async.
Basically code like this:
async fn foo() -> uint {
let a: int = compute_a();
let b: int = compute_b();
let c: char = await read_char();
let r: uint = compute_r(a, b, c);
return r;
}
becomes after the compiler performs CPS transform:
// assume that we have trait Continuation<T> {fn continue<T>(~self, v: T);}
// assume that cps_read_char is provided by the runtime and tells a main loop
to read a char and then schedule a new task running the passed continuation
struct foo_Continuation(~Continuation<uint>, int, int);
fn cps_foo(continuation: ~Continuation<uint>) {
let a: int = compute_a();
let b: int = compute_b();
return cps_read_char(~foo_Continuation(continuation, a, b));
}
impl Continuation<char> for foo_Continuation
{
fn continue(~self, c: char) {
let (continuation, a, b) = *self;
let r = compute_r(a, b, c);
continuation.continue(r);
}
}
and then a future-based version can also be generated by the compiler based on
the CPS transform results:
// assume that Continuation<T> is implemented on TaskFuture<T> and causes the
TaskFuture to be completed with the value
fn future_foo() -> ~TaskFuture<int> {
let f = ~TaskFuture::new();
cps_foo(f);
return f;
}
Note that if foo() had taken a borrowed pointer with lifetime 'a, then the CPS
version becomes unsafe, and TaskFuture would also need an 'a parameter.
Also, one can use a borrowed pointer instead of an owned pointer for
continuations and futures, but then they need to be waited on before its
lifetime region ends.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev