Skip to content

Instantly share code, notes, and snippets.

Created July 5, 2015 16:48
Show Gist options
  • Save anonymous/84941660a9dd99b86bfd to your computer and use it in GitHub Desktop.
Save anonymous/84941660a9dd99b86bfd to your computer and use it in GitHub Desktop.
/// 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 = &current.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