R: add hash-map and metadata support.
[jackhill/mal.git] / r / core.r
CommitLineData
01feedfe
JM
1..core.. <- TRUE
2
3if(!exists("..types..")) source("types.r")
4if(!exists("..printer..")) source("printer.r")
5
6
c30efef4
JM
7# String functions
8
36737ae5
JM
9pr_str <- function(...)
10 .pr_list(list(...), print_readably=TRUE, join=" ")
01feedfe 11
36737ae5
JM
12str <- function(...)
13 .pr_list(list(...), print_readably=FALSE, join="")
01feedfe
JM
14
15prn <- function(...) {
36737ae5
JM
16 cat(.pr_list(list(...), print_readably=TRUE, join=" "))
17 cat("\n")
01feedfe
JM
18 nil
19}
20
21println <- function(...) {
36737ae5
JM
22 cat(.pr_list(list(...), print_readably=FALSE, join=" "))
23 cat("\n")
01feedfe
JM
24 nil
25}
26
36737ae5
JM
27# Hash Map functions
28do_get <- function(hm,k) {
29 if (class(hm) == "nil") return(nil)
30 v <- hm[[k]]
31 if (is.null(v)) nil else v
32}
33contains_q <-function(hm,k) {
34 if (class(hm) == "nil") return(FALSE)
35 if (is.null(hm[[k]])) FALSE else TRUE
36}
37
c30efef4
JM
38# Sequence functions
39cons <- function(a,b) {
40 new_lst <- append(list(a), b)
8128c69a 41 new.listl(new_lst)
c30efef4
JM
42}
43
44do_concat <- function(...) {
45 new_lst <- list()
46 for(l in list(...)) {
47 new_lst <- append(new_lst, l)
48 }
8128c69a
JM
49 new.listl(new_lst)
50}
51
52do_apply <- function(f, ...) {
53 p <- list(...)
54 args <- list()
55 if (length(p) > 1) {
56 for(l in slice(p, 1, length(p)-1)) {
57 args[[length(args)+1]] <- l
58 }
59 }
60 args <- append(args, p[[length(p)]])
61 fapply(f, args)
62}
63
64map <- function(f, seq) {
65 new.listl(lapply(seq, function(el) fapply(f, el)))
c30efef4
JM
66}
67
36737ae5
JM
68# Metadata functions
69with_meta <- function(obj, m) {
70 new_obj <- .clone(obj)
71 attr(new_obj, "meta") <- m
72 new_obj
73}
74
75meta <- function(obj) {
76 m <- attr(obj, "meta")
77 if (is.null(m)) nil else m
78}
79
01feedfe
JM
80core_ns <- list(
81 "="=function(a,b) .equal_q(a,b),
8128c69a
JM
82 "throw"=function(err) throw(err),
83 "nil?"=.nil_q,
84 "true?"=.true_q,
85 "false?"=.false_q,
86 "symbol?"=.symbol_q,
87 "symbol"=new.symbol,
88 "symbol?"=.symbol_q,
01feedfe
JM
89
90 "pr-str"=pr_str,
91 "str"=str,
92 "prn"=prn,
93 "println"=println,
8128c69a 94 "readline"=readline,
c30efef4
JM
95 "read-string"=function(str) read_str(str),
96 "slurp"=function(path) readChar(path, file.info(path)$size),
01feedfe
JM
97 "<"=function(a,b) a<b,
98 "<="=function(a,b) a<=b,
99 ">"=function(a,b) a>b,
100 ">="=function(a,b) a>=b,
101 "+"=function(a,b) a+b,
102 "-"=function(a,b) a-b,
103 "*"=function(a,b) a*b,
104 "/"=function(a,b) a/b,
105
8128c69a 106 "list"=new.list,
01feedfe 107 "list?"=function(a) .list_q(a),
8128c69a
JM
108 "vector"=new.vector,
109 "vector?"=function(a) .vector_q(a),
36737ae5
JM
110 "hash-map"=new.hash_map,
111 "map?"=function(a) .hash_map_q(a),
112 "assoc"=function(hm,...) .assoc(hm,list(...)),
113 "dissoc"=function(hm,...) .dissoc(hm,list(...)),
114 "get"=do_get,
115 "contains?"=contains_q,
116 "keys"=function(hm) new.listl(ls(hm)),
117 "vals"=function(hm) new.listl(lapply(ls(hm), function(x) hm[[x]])),
01feedfe 118
8128c69a 119 "sequential?"=.sequential_q,
c30efef4 120 "cons"=cons,
8128c69a
JM
121 "concat"=do_concat,
122 "nth"=function(a,b) if (length(a) < b+1) nil else a[[b+1]],
123 "first"=function(a) if (length(a) < 1) nil else a[[1]],
124 "rest"=function(a) new.listl(slice(a,2)),
36737ae5
JM
125 "empty?"=function(a) .sequential_q(a) && length(a) == 0,
126 "count"=function(a) length(a),
8128c69a 127 "apply"=do_apply,
36737ae5
JM
128 "map"=map,
129
130 "with-meta"=with_meta,
131 "meta"=meta
01feedfe 132)