Created
July 15, 2019 03:55
-
-
Save kendru/8c3a781b4cdf53c2bff6af72639fbf0d to your computer and use it in GitHub Desktop.
Example implementation of the visitor pattern in Rust
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
pub trait Visitable { | |
fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result; | |
} | |
pub trait Visitor { | |
type Result; | |
fn visit_num(&mut self, num: &Num) -> Self::Result; | |
fn visit_add<T, U>(&mut self, add: &Add<T, U>) -> Self::Result | |
where T: Visitable, U: Visitable; | |
fn visit_sub<T, U>(&mut self, sub: &Sub<T, U>) -> Self::Result | |
where T: Visitable, U: Visitable; | |
} | |
struct Num(i64); | |
impl Visitable for Num { | |
fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result { | |
visitor.visit_num(self) | |
} | |
} | |
struct Add<T: Visitable, U: Visitable>(T, U); | |
impl<T: Visitable, U: Visitable> Visitable for Add<T, U> { | |
fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result { | |
visitor.visit_add(self) | |
} | |
} | |
struct Sub<T: Visitable, U: Visitable>(T, U); | |
impl<T: Visitable, U: Visitable> Visitable for Sub<T, U> { | |
fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result { | |
visitor.visit_sub(self) | |
} | |
} | |
struct Interpreter; | |
impl Visitor for Interpreter { | |
type Result = i64; | |
fn visit_num(&mut self, num: &Num) -> Self::Result { | |
num.0 | |
} | |
fn visit_add<T, U>(&mut self, add: &Add<T, U>) -> Self::Result | |
where T:Visitable, U: Visitable { | |
let Add(lh, rh) = add; | |
lh.accept(self) + rh.accept(self) | |
} | |
fn visit_sub<T, U>(&mut self, sub: &Sub<T, U>) -> Self::Result | |
where T:Visitable, U: Visitable { | |
let Sub(lh, rh) = sub; | |
lh.accept(self) - rh.accept(self) | |
} | |
} | |
#[cfg(test)] | |
mod test { | |
use super::*; | |
#[test] | |
fn evaluates_tree_with_visitor() { | |
let mut interpreter = Interpreter; | |
let expr = Add(Sub(Num(42), Num(7)), Num(17)); | |
assert_eq!(52, expr.accept(&mut interpreter)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment