1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-11 13:55:55 +03:00

add core collection functions

This commit is contained in:
Fabian 2021-04-05 20:51:54 +02:00 committed by Joel Martin
parent f2a37a3ae4
commit f8faaec47f
2 changed files with 46 additions and 9 deletions

View File

@ -9,7 +9,11 @@ and collectLists' (LIST l::rest) acc = collectLists' rest (l::acc)
| collectLists' [] acc = SOME (rev acc)
| collectLists' _ _ = NONE
val coreList = [
fun buildMap (k::v::rest) acc = buildMap rest (malAssoc acc k v)
| buildMap [] acc = MAP (rev acc)
| buildMap _ _ = raise NotApplicable "maps can only be constructed from an even number of arguments"
val coreCollection = [
SYMBOL "list",
FN (fn args => LIST args),
@ -61,7 +65,38 @@ val coreList = [
FN (fn [LIST l] => (case l of (_::xs) => LIST xs | _ => LIST [])
| [VECTOR v] => (case v of (_::xs) => LIST xs | _ => LIST [])
| [NIL] => LIST []
| x => raise NotApplicable "rest requires a list or vector or nil")
| x => raise NotApplicable "rest requires a list or vector or nil"),
SYMBOL "vector",
FN (fn args => VECTOR args),
SYMBOL "hash-map",
FN (fn args => buildMap args []),
SYMBOL "assoc",
FN (fn (MAP m :: (args as _::_)) => buildMap args m
| _ => raise NotApplicable "assoc requires a map and some arguments to add"),
SYMBOL "dissoc",
FN (fn (MAP m :: (args as _::_)) => MAP (foldl (fn (k, acc) => malDissoc acc k) m args)
| _ => raise NotApplicable "dissoc requires a map and some arguments to remove"),
SYMBOL "get",
FN (fn [MAP m, k] => valOrElse (malGet m k) (fn () => NIL)
| [NIL, _] => NIL
| _ => raise NotApplicable "get requires a map and a key"),
SYMBOL "contains?",
FN (fn [MAP m, k] => BOOL (List.exists (fn (k', _) => malEq (k, k')) m)
| _ => raise NotApplicable "contains? requires a map and a key"),
SYMBOL "keys",
FN (fn [MAP m] => LIST (map #1 m)
| _ => raise NotApplicable "keys requires a map"),
SYMBOL "vals",
FN (fn [MAP m] => LIST (map #2 m)
| _ => raise NotApplicable "vals requires a map")
]
(* N.B. adds extra newline at end *)
@ -80,10 +115,10 @@ val coreIo = [
| _ => raise NotApplicable "'slurp' requires a string filename"),
SYMBOL "prn",
FN (fn args => args |> List.map prReadableStr |> String.concatWith " " |> malPrint),
FN (fn args => args |> map prReadableStr |> String.concatWith " " |> malPrint),
SYMBOL "println",
FN (fn args => args |> List.map prStr |> String.concatWith " " |> malPrint)
FN (fn args => args |> map prStr |> String.concatWith " " |> malPrint)
]
fun arithFolder n f (INT next, INT prev) = INT (f (prev, next))
@ -157,17 +192,17 @@ val coreMeta = [
val coreString = [
SYMBOL "pr-str",
FN (fn args => args |> List.map prReadableStr |> String.concatWith " " |> STRING),
FN (fn args => args |> map prReadableStr |> String.concatWith " " |> STRING),
SYMBOL "str",
FN (fn args => args |> List.map prStr |> String.concatWith "" |> STRING),
FN (fn args => args |> map prStr |> String.concatWith "" |> STRING),
SYMBOL "symbol",
FN (fn [STRING s] => SYMBOL s
| _ => raise NotApplicable "symbol requires a string"),
SYMBOL "keyword",
FN (fn [STRING s] => KEYWORD s
FN (fn [STRING s] => KEYWORD s | [kw as KEYWORD _] => kw
| _ => raise NotApplicable "keyword requires a string")
]
@ -217,7 +252,7 @@ val coreFn = [
]
val coreNs = List.concat [
coreList,
coreCollection,
coreIo,
coreCmp,
coreMeta,

View File

@ -38,4 +38,6 @@ and mapEq a b =
and malGet m k = m |> List.find (fn (k',_) => malEq (k, k')) |> Option.map #2
and malAssoc m k v = (k, v) :: (m |> List.filter (not o (fn (k', _) => malEq (k, k'))))
and malAssoc m k v = (k, v) :: (malDissoc m k)
and malDissoc m k = m |> List.filter (not o (fn (k', _) => malEq (k, k')))