mirror of
https://github.com/teo3300/rust-mal.git
synced 2026-01-12 01:05:32 +01:00
Adding map for HOF
This commit is contained in:
4
Makefile
4
Makefile
@ -6,8 +6,10 @@ build-release:
|
|||||||
test:
|
test:
|
||||||
cargo test --release
|
cargo test --release
|
||||||
|
|
||||||
install: build-release
|
conf:
|
||||||
mkdir -p ${HOME}/.config/mal
|
mkdir -p ${HOME}/.config/mal
|
||||||
cp -f core/core.mal ${HOME}/.config/mal/
|
cp -f core/core.mal ${HOME}/.config/mal/
|
||||||
|
|
||||||
|
install: build-release conf
|
||||||
sudo cp target/release/rust-mal /usr/local/bin/mal
|
sudo cp target/release/rust-mal /usr/local/bin/mal
|
||||||
sudo chown ${USER} /usr/local/bin/mal
|
sudo chown ${USER} /usr/local/bin/mal
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use std::{cell::RefCell, env, rc::Rc};
|
use std::{cell::RefCell, env, rc::Rc};
|
||||||
|
|
||||||
use crate::env::{
|
use crate::env::{
|
||||||
any_zero, arithmetic_op, car, comparison_op, env_new, env_set, mal_car, mal_cdr, mal_exit, Env,
|
any_zero, arithmetic_op, car, comparison_op, env_new, env_set, mal_car, mal_cdr, mal_exit,
|
||||||
|
mal_map, Env,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the first time I implement a macro, and I'm copying it
|
// This is the first time I implement a macro, and I'm copying it
|
||||||
@ -80,6 +81,7 @@ pub fn ns_init() -> Env {
|
|||||||
"atom" => Fun(|a| Ok(Atom(Rc::new(RefCell::new(car(a).unwrap_or_default().clone())))), "Return an atom pointing to the given arg"),
|
"atom" => Fun(|a| Ok(Atom(Rc::new(RefCell::new(car(a).unwrap_or_default().clone())))), "Return an atom pointing to the given arg"),
|
||||||
"deref" => Fun(|a| if_atom!(car(a)?), "Return the content of the atom argumet"),
|
"deref" => Fun(|a| if_atom!(car(a)?), "Return the content of the atom argumet"),
|
||||||
"reset!" => Fun(reset_bang, "Change the value of the Atom (frist argument) to the second argument"),
|
"reset!" => Fun(reset_bang, "Change the value of the Atom (frist argument) to the second argument"),
|
||||||
|
"map" => Fun(mal_map, "Apply the first argument to all the elements of the second arguments"),
|
||||||
"env" => Fun(|a| match env::var(car(a)?.if_string()?) {
|
"env" => Fun(|a| match env::var(car(a)?.if_string()?) {
|
||||||
Ok(s) => Ok(Str(s.into())),
|
Ok(s) => Ok(Str(s.into())),
|
||||||
_ => Ok(Nil),
|
_ => Ok(Nil),
|
||||||
|
|||||||
32
src/env.rs
32
src/env.rs
@ -189,6 +189,38 @@ pub fn car_cdr(list: &[MalType]) -> Result<(&MalType, &[MalType]), MalErr> {
|
|||||||
Ok((car(list)?, cdr(list)))
|
Ok((car(list)?, cdr(list)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mal_map(args: &[MalType]) -> MalRet {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
let (lambda, list) = car_cdr(args)?;
|
||||||
|
let list = car(list)?.if_list()?;
|
||||||
|
match lambda {
|
||||||
|
M::Fun(func, _) => {
|
||||||
|
for el in list {
|
||||||
|
ret.push(func(&[el.clone()])?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
M::MalFun {
|
||||||
|
params, ast, env, ..
|
||||||
|
} => {
|
||||||
|
for el in list {
|
||||||
|
let inner_env = env_binds(env.clone(), params, &[el.clone()])?;
|
||||||
|
match ast.as_ref() {
|
||||||
|
M::List(ops) => {
|
||||||
|
let mut last = MalType::Nil;
|
||||||
|
for x in &ops[0..ops.len()] {
|
||||||
|
last = eval(x, inner_env.clone())?;
|
||||||
|
}
|
||||||
|
ret.push(last)
|
||||||
|
}
|
||||||
|
_ => scream!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => scream!(),
|
||||||
|
};
|
||||||
|
Ok(MalType::List(ret.into()))
|
||||||
|
}
|
||||||
|
|
||||||
fn first(list: &[MalType]) -> &[MalType] {
|
fn first(list: &[MalType]) -> &[MalType] {
|
||||||
if list.len() > 1 {
|
if list.len() > 1 {
|
||||||
&list[..list.len() - 1]
|
&list[..list.len() - 1]
|
||||||
|
|||||||
@ -60,4 +60,9 @@ mod functional {
|
|||||||
fn car_cdr() {
|
fn car_cdr() {
|
||||||
test!("car-cdr")
|
test!("car-cdr")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn map() {
|
||||||
|
test!("map")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
tests/map.mal
Normal file
5
tests/map.mal
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
; builtin map
|
||||||
|
(assert-eq '((1) (2) (3)) (map list '(1 2 3)))
|
||||||
|
|
||||||
|
; lambda map
|
||||||
|
(assert-eq '(2 3 4) (map (fn* [x] (+ x 1)) '(1 2 3)))
|
||||||
Reference in New Issue
Block a user