Created
July 5, 2015 16:48
-
-
Save anonymous/84941660a9dd99b86bfd to your computer and use it in GitHub Desktop.
This file contains 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
/// Lisp datatypes. A Cons is a | |
/// pointer to a pair, not the pair itself. | |
#[derive(PartialEq, Clone, Debug)] | |
pub enum Data { | |
Nil, | |
Symbol(String), | |
Float(f32), | |
Func(String), | |
Cons(Box<(Data,Data)>) | |
} | |
impl Data { | |
pub fn atom(&self) -> bool { | |
match *self { | |
Cons(_) => false, | |
_ => true, | |
} | |
} | |
pub fn car (&self) -> &Data { | |
match *self { | |
Cons(ref c) => &c.0, | |
Nil => self, | |
_ => panic!("Not a cons!") | |
} | |
} | |
pub fn cdr (&self) -> &Data { | |
match *self { | |
Cons(ref c) => &c.1, | |
Nil => self, | |
_ => panic!("Not a cons!") | |
} | |
} | |
pub fn cadr (&self) -> &Data { | |
self.cdr().car() | |
} | |
/// Reverses a list in place. Non-consing. | |
pub fn nreverse (self) -> Data{ | |
let mut curr = self; | |
let mut prv = Nil; | |
while curr != Nil { | |
match curr { | |
Cons(ref mut c) =>{ | |
let next = &mut c.1; | |
swap(next, &mut prv); | |
} | |
_ => panic!("Not a proper list!"), | |
}; | |
swap(&mut curr, &mut prv); | |
} | |
prv | |
} | |
pub fn map (&self, f: fn(&Data) -> Data) -> Data { | |
/* Applies f to every element in the list. */ | |
if self.atom() {panic!("Not a list!")}; | |
let mut mapped = Nil; | |
let mut curr = self; | |
while *curr != Nil { | |
mapped = (f(curr.car())).cons(mapped); | |
curr = &curr.cdr(); | |
} | |
mapped.nreverse() | |
} | |
pub fn len(&self) -> usize { | |
match *self { | |
Nil => 0, | |
Cons(_) => { | |
let mut count:usize = 1; | |
let mut current = self; | |
while *current.cdr() != Nil { | |
match *current.cdr() { | |
Cons(_) => { | |
count += 1; | |
current = ¤t.cdr(); | |
}, | |
_ => return count + 1 | |
} | |
} | |
count | |
}, | |
_ => panic!("Not a list!"), | |
} | |
} | |
pub fn last(&self) -> &Data { | |
if self.atom() {panic!("Not a proper list.")}; | |
let mut c = self; | |
while *c.cdr() != Nil { | |
c = c.cdr(); | |
} | |
c.car() | |
} | |
/// Constructs a cons. Transfers ownership to new cons. | |
pub fn cons (self, cdr:Data) -> Data { | |
Cons( Box::new( (self,cdr) ) ) | |
} | |
} | |
/// Pretty printing support. | |
impl fmt::Display for Data { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
match *self { | |
Float(s) => write!(f, "{}", s), | |
Nil => write!(f, "Nil"), | |
Cons(_) => { | |
write!(f, "({}", self.car()); | |
let mut focus = self.cdr(); | |
while *focus != Nil { | |
match *focus { | |
Nil => unreachable!(), | |
Cons(_) => { | |
write!(f, " {}", focus.car()); | |
focus = focus.cdr(); | |
} | |
_ => return write!(f, " . {})", focus) | |
} | |
} | |
write!(f, ")") | |
} | |
Symbol(ref s) => write!(f, "{}", *s), | |
Func(ref s) => write!(f, "#<Function {}>", *s), | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment