Skip to content

Instantly share code, notes, and snippets.

@Geal
Last active September 13, 2015 19:00
Show Gist options
  • Save Geal/617f2f55688e723a6340 to your computer and use it in GitHub Desktop.
Save Geal/617f2f55688e723a6340 to your computer and use it in GitHub Desktop.
nom iteratees
// 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