add reverse, snippet for prepend implementation
This commit is contained in:
parent
6961fcc9fa
commit
928c9b91ed
6 changed files with 288 additions and 25 deletions
|
|
@ -103,3 +103,84 @@ pub fn cdr_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
Err("impossible condition: argument to cdr not a list".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub const POP_DOCSTRING: &str = "Takes a single argument, expected to be a list.
|
||||
Returns a list containing the first element, and the rest of the elements.
|
||||
|
||||
Example: (pop (1 2 3)) -> (1 (2 3)).
|
||||
|
||||
The head can then be accessed by car and the rest can be accessed by cdr.";
|
||||
|
||||
pub fn pop_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
if let Ctr::Seg(ref s) = *ast.car {
|
||||
if s.len() < 1 {
|
||||
return Err("cannot pop from empty list".to_string());
|
||||
}
|
||||
let mut ret = Seg::new();
|
||||
ret.append(s.car.clone());
|
||||
if let Ctr::Seg(ref s2) = *s.cdr {
|
||||
ret.append(Box::new(Ctr::Seg(s2.clone())));
|
||||
} else {
|
||||
ret.append(Box::new(Ctr::Seg(Seg::new())));
|
||||
}
|
||||
Ok(Ctr::Seg(ret))
|
||||
} else {
|
||||
Err("Impossible condition: arg not a list".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEQUEUE_DOCSTRING: &str = "Takes a single argument, expected to be a list.
|
||||
Returns a list containing the last element, and the rest of the elements.
|
||||
|
||||
Example: (dq (1 2 3)) -> (3 (1 2)).
|
||||
|
||||
The last element can then be accessed by car and the rest can be accessed by cdr.";
|
||||
|
||||
pub fn dequeue_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
if let Ctr::Seg(ref s) = *ast.car {
|
||||
if s.len() < 1 {
|
||||
return Err("cannot dequeue from empty list".to_string());
|
||||
}
|
||||
let mut rest = Seg::new();
|
||||
let mut iter = s;
|
||||
while *iter.cdr != Ctr::None {
|
||||
rest.append(Box::new(*iter.car.clone()));
|
||||
if let Ctr::Seg(ref next) = *iter.cdr {
|
||||
iter = next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut ret = Seg::new();
|
||||
match *iter.car {
|
||||
Ctr::Seg(ref s) => {
|
||||
ret.append(s.car.clone());
|
||||
}
|
||||
_ => ret.append(iter.car.clone()),
|
||||
}
|
||||
|
||||
ret.append(Box::new(Ctr::Seg(rest)));
|
||||
|
||||
Ok(Ctr::Seg(ret))
|
||||
} else {
|
||||
Err("Impossible condition: arg not a list".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub const REVERSE_DOCSTRING: &str = "Takes a single argument, expected to be a list.
|
||||
Returns the same list, but in reverse order.";
|
||||
|
||||
pub fn reverse_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
if let Ctr::Seg(ref s) = *ast.car {
|
||||
let mut ret = Seg::new();
|
||||
s.circuit_reverse(&mut |arg: &Ctr| -> bool {
|
||||
ret.append(Box::new(arg.clone()));
|
||||
true
|
||||
});
|
||||
|
||||
Ok(Ctr::Seg(ret))
|
||||
} else {
|
||||
Err("Impossible condition: arg not a list".to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue