use std::comm::{Receiver, channel}; use std::io; use std::mem::replace; use std::task::spawn; struct Future<'a, A> { state: FutureState<'a, A> } enum FutureState<'a, A> { Pending(proc():'a -> A), Evaluating, // This state is only here to satify the compiler in get_ref Forced(A), } /* * This is based on the rust std::sync::Future * https://github.com/rust-lang/rust/blob/master/src/libstd/sync/future.rs * with the addition of map and and_then. * Note, I am very new to rust and much of this is non-idiomatic (and probably dumb and/or broken, but it runs). * * This future is only designed to either be asynchronous and evaluate in another task, * or lift a literal value into the future. * * Note this Future is lazy and mapping and and_then procs are called as needed to evaluate * get_ref calls. If there are side-effects in those functions, all leaf Futures should have * their get_ref fn called for the logic to be correct. * * For me, it is still unclear where the right parts of the design space are: there are * interesting trade-offs between using references and lifetimes vs boxes vs cloning. * Here we avoid copying/cloning or GC/ref-counting in map/and_then. */ impl<'a, A> Future<'a, A> { /* * This is the function to lift something into the future (monad) */ pub fn from(val: A) -> Future<'a, A> { Future { state: Forced(val) } } /* * This can be used on non-mutable refs if the future is Forced */ pub fn get_opt<'b>(&'b self) -> Option<&'b A> { match self.state { Forced(ref a) => return Some(a), _ => return None } } pub fn get_ref<'b>(&'b mut self) -> &'b A { match self.state { Forced(ref a) => return a, Pending(_) => { /* * This is copying the sync::Future since * we can't take p and evaluate it in one go, and * we can't call p if we are just borrowing self (as far as I can see) */ match replace(&mut self.state, Evaluating) { Forced(_) | Evaluating => panic!("Unreachable"), Pending(p) => { self.state = Forced(p()); return self.get_ref() } } } Evaluating => panic!("Unreachable") } } /* * Should this be a proc or a closure? We only call it once. */ pub fn map(&mut self, mapfn: proc(&A) -> B) -> Future<'a, B> { match self.state { Forced(ref a) => Future { state: Forced(mapfn(a)) }, Pending(_) => Future { state: Pending(proc() { mapfn(self.get_ref()) }) }, Evaluating => panic!("Unreachable") } } /* * This is the monadic bind function * * Should this be a proc or a closure? We only call it once. */ pub fn and_then<'b, B>(&mut self, bindfn: proc(&A) -> Future<'b, B>) -> Future<'b, B> { match self.state { Forced(ref a) => bindfn(a), Pending(_) => Future { state: Pending(proc() { let a = self.get_ref(); let mut fb = bindfn(a); // Force the future, but ignore the reference, use move semantics below let _ = fb.get_ref(); match fb.state { Forced(b) => return b, _ => panic!("get_ref should have forced us") } }) }, Evaluating => panic!("Unreachable") } } } impl<'a, A:Send> Future<'a, A> { pub fn async(f: proc(): Send -> A) -> Future<'a, A> { let (tx, rx) = channel(); spawn(proc() { tx.send(f()) }); Future { state: Pending(proc() { rx.recv() }) } } } fn main() { println!("please enter a line:"); let input = io::stdin().read_line().ok().expect("Failed to read a line"); println!("You entered: {}", input) println!("string had len = {}", Future::from(input.clone()) .map(proc(s) { return s.len() }) .get_ref() ) println!("string had len (and_then) = {}", Future::from(input) .and_then(proc(s) { let sc = s.clone(); Future::async(proc() { return sc.len() } ) }) .get_ref() ) }