Skip to content

Instantly share code, notes, and snippets.

@kendru
Created July 15, 2019 03:55
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kendru/8c3a781b4cdf53c2bff6af72639fbf0d to your computer and use it in GitHub Desktop.
Save kendru/8c3a781b4cdf53c2bff6af72639fbf0d to your computer and use it in GitHub Desktop.
Example implementation of the visitor pattern in Rust
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