Last active
September 13, 2015 19:00
-
-
Save Geal/617f2f55688e723a6340 to your computer and use it in GitHub Desktop.
nom iteratees
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Context: | |
// * Rust n'a pas de TCO, donc on ne peut pas faire de récursion facilement | |
// * la gestion de l'ownership fait que le résultat d'une passe sur le | |
// contenu du Producer ne vivra pas plus longtemps que son buffer (sauf si on cpone les données) | |
// * les Producers et Consumers actuels passent leur temps à copier des buffers, | |
// je veux limiter ça au Producer | |
type Computation<I,O,S,E> = Fn(S, Input<I>) -> (I,Consumer<I,O,S,E>); | |
enum Input<I> { | |
Element<I>, | |
Empty, | |
Eof | |
} | |
// I pour input, O pour output, S pour State, E pour Error | |
// S et E ont des types par défaut, donc on n'est pasobligé de les préciser | |
enum Consumer<I,O,S=(),E=()> { | |
Done(O), // output | |
Error(E), | |
Continue(S, Computation<I,O,S,E>) // on passe un état au lieu de passer une closure | |
} | |
impl Consumer<I,O,S,E> { | |
fn new(f: Computation<I,O,S,E>, initial: S) -> Consumer<I,O,S,E> { | |
Continue(initial, f) | |
} | |
fn fold(f: (S,I) -> S, initial: S) -> Consumer<I,O,S,E> { | |
fn step(state:S, input: Input<I>) -> (I,Consumer<I,S,S,E>) { | |
match input { | |
Element(i) => (Empty, Continue(f(state, i), step)), | |
Empty => (Empty, Continue(s, step)), | |
Eof => (Eof, Done(s)) | |
} | |
} | |
Continue(initial, f) | |
} | |
fn map<F,P>(&self, f:F) -> Consumer<I,P,S,E> where F: Fn(O) -> P { | |
match *self { | |
Error(e) => Error(e), | |
Done(o) => Done(f(o)), | |
Continue(s, step) => { | |
fn mapped(state:S, input:Input<I>) -> (I,Consumer<I,O,S,E>) { | |
step(state, input).map(f) | |
} | |
} | |
} | |
} | |
fn run(&self) -> Option<&O> { | |
if let &Done(_, ref o) = self { | |
Some(o) | |
} else { | |
None | |
} | |
} | |
} | |
// ex: | |
fn head_step<I>(state: (), Input<I>) -> (I,Consumer<I,Option<I>,(),()>) { | |
match input { | |
Element(i) => (Eof, Done(Some(i))), | |
Empty => (Empty, Continue((), head_step)), | |
Eof => (Eof, Error(None)) | |
} | |
} | |
let head = Continue((), head_step); | |
trait Producer<I> { | |
fn apply<O,S,E>(input: Consumer<I,O,S,E>) -> Consumer<I,O,S,E>; // applique le consumer sur la donnée contenue actuellement dans le producer | |
fn run<O>(input: ConsumerState<I,O,S,E>) -> Option<O>; | |
// fn fromFile, FromSocket, fromRead | |
} | |
struct ProducerOnce<I> { | |
value: I | |
} | |
impl Producer<I> for ProducerOnce<I> { | |
fn apply<O,S,E>(&self, consumer: Consumer<I,O,S,E>) -> Consumer<I,O,S,E> { | |
match consumer { | |
Continue(s, f) => { | |
let (_, c) = f(s, self.value); | |
c | |
} | |
} | |
} | |
fn run<O>(&self, consumer: Consumer<I,O,S,E>) -> Option<O> { | |
self.apply(consumer).run() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment