2015-06-11 05:59:01 +03:00
|
|
|
#import copy, time
|
|
|
|
import time
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
import mal_types as types
|
2015-06-11 08:15:07 +03:00
|
|
|
from mal_types import (throw_str,
|
|
|
|
MalType, MalMeta, nil, true, false,
|
2015-06-11 05:59:01 +03:00
|
|
|
MalInt, MalSym, MalStr,
|
2015-06-11 07:25:55 +03:00
|
|
|
MalList, MalVector, MalHashMap,
|
|
|
|
MalAtom, MalFunc)
|
2015-06-09 05:58:37 +03:00
|
|
|
import mal_readline
|
|
|
|
import reader
|
|
|
|
import printer
|
|
|
|
|
|
|
|
# General functions
|
2015-06-10 07:07:03 +03:00
|
|
|
def wrap_tf(tf):
|
|
|
|
if tf: return true
|
|
|
|
else: return false
|
2015-06-09 05:58:37 +03:00
|
|
|
|
2015-06-10 07:07:03 +03:00
|
|
|
def do_equal(args): return wrap_tf(types._equal_Q(args[0], args[1]))
|
|
|
|
|
|
|
|
# Errors/Exceptions
|
|
|
|
def throw(args):
|
|
|
|
raise types.MalException(args[0])
|
|
|
|
|
|
|
|
# Scalar functions
|
|
|
|
def nil_Q(args): return wrap_tf(types._nil_Q(args[0]))
|
|
|
|
def true_Q(args): return wrap_tf(types._true_Q(args[0]))
|
|
|
|
def false_Q(args): return wrap_tf(types._false_Q(args[0]))
|
2016-02-11 18:19:53 +03:00
|
|
|
def string_Q(args): return wrap_tf(types._string_Q(args[0]))
|
2015-06-10 07:07:03 +03:00
|
|
|
def symbol(args):
|
|
|
|
a0 = args[0]
|
|
|
|
if isinstance(a0, MalStr):
|
|
|
|
return types._symbol(a0.value)
|
|
|
|
elif isinstance(a0, MalSym):
|
|
|
|
return a0
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("symbol called on non-string/non-symbol")
|
2015-06-10 07:07:03 +03:00
|
|
|
def symbol_Q(args): return wrap_tf(types._symbol_Q(args[0]))
|
|
|
|
def keyword(args): return types._keyword(args[0])
|
|
|
|
def keyword_Q(args): return wrap_tf(types._keyword_Q(args[0]))
|
2017-10-12 04:18:50 +03:00
|
|
|
def number_Q(args): return wrap_tf(types._int_Q(args[0]))
|
|
|
|
def function_Q(args): return wrap_tf(types._function_Q(args[0]) and not args[0].ismacro)
|
|
|
|
def macro_Q(args): return wrap_tf(types._function_Q(args[0]) and args[0].ismacro)
|
2015-06-10 05:21:12 +03:00
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
# String functions
|
|
|
|
def pr_str(args):
|
|
|
|
parts = []
|
|
|
|
for exp in args.values: parts.append(printer._pr_str(exp, True))
|
|
|
|
return MalStr(u" ".join(parts))
|
|
|
|
|
|
|
|
def do_str(args):
|
|
|
|
parts = []
|
|
|
|
for exp in args.values: parts.append(printer._pr_str(exp, False))
|
|
|
|
return MalStr(u"".join(parts))
|
|
|
|
|
|
|
|
def prn(args):
|
|
|
|
parts = []
|
|
|
|
for exp in args.values: parts.append(printer._pr_str(exp, True))
|
|
|
|
print(u" ".join(parts))
|
|
|
|
return nil
|
|
|
|
|
|
|
|
def println(args):
|
|
|
|
parts = []
|
|
|
|
for exp in args.values: parts.append(printer._pr_str(exp, False))
|
|
|
|
print(u" ".join(parts))
|
|
|
|
return nil
|
|
|
|
|
2015-06-10 07:22:48 +03:00
|
|
|
def do_readline(args):
|
|
|
|
prompt = args[0]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(prompt, MalStr):
|
|
|
|
throw_str("readline prompt is not a string")
|
2015-06-11 07:25:55 +03:00
|
|
|
try:
|
|
|
|
return MalStr(unicode(mal_readline.readline(str(prompt.value))))
|
|
|
|
except EOFError:
|
|
|
|
return nil
|
2015-06-10 07:22:48 +03:00
|
|
|
|
2015-06-09 07:09:17 +03:00
|
|
|
def read_str(args):
|
|
|
|
a0 = args[0]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a0, MalStr):
|
|
|
|
throw_str("read-string of non-string")
|
2015-06-09 07:09:17 +03:00
|
|
|
return reader.read_str(str(a0.value))
|
|
|
|
|
|
|
|
def slurp(args):
|
|
|
|
a0 = args[0]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a0, MalStr):
|
|
|
|
throw_str("slurp with non-string filename")
|
2015-06-09 07:09:17 +03:00
|
|
|
return MalStr(unicode(open(str(a0.value)).read()))
|
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
# Number functions
|
|
|
|
def lt(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("< called on non-integer")
|
2015-06-10 07:07:03 +03:00
|
|
|
return wrap_tf(a.value < b.value)
|
2015-06-09 05:58:37 +03:00
|
|
|
def lte(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("<= called on non-integer")
|
2015-06-10 07:07:03 +03:00
|
|
|
return wrap_tf(a.value <= b.value)
|
2015-06-09 05:58:37 +03:00
|
|
|
def gt(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("> called on non-integer")
|
2015-06-10 07:07:03 +03:00
|
|
|
return wrap_tf(a.value > b.value)
|
2015-06-09 05:58:37 +03:00
|
|
|
def gte(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str(">= called on non-integer")
|
2015-06-10 07:07:03 +03:00
|
|
|
return wrap_tf(a.value >= b.value)
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
def plus(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("+ called on non-integer")
|
2015-06-09 05:58:37 +03:00
|
|
|
return MalInt(a.value+b.value)
|
|
|
|
def minus(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("- called on non-integer")
|
2015-06-09 05:58:37 +03:00
|
|
|
return MalInt(a.value-b.value)
|
|
|
|
def multiply(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("* called on non-integer")
|
2015-06-09 05:58:37 +03:00
|
|
|
return MalInt(a.value*b.value)
|
|
|
|
def divide(args):
|
|
|
|
a, b = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(a, MalInt) or not isinstance(b, MalInt):
|
|
|
|
throw_str("/ called on non-integer")
|
|
|
|
if b.value == 0:
|
|
|
|
throw_str("divide by zero")
|
2015-06-09 05:58:37 +03:00
|
|
|
return MalInt(int(a.value/b.value))
|
|
|
|
|
2015-06-11 07:25:55 +03:00
|
|
|
def time_ms(args):
|
|
|
|
return MalInt(int(time.time() * 1000))
|
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
|
2015-06-11 05:59:01 +03:00
|
|
|
# Hash map functions
|
|
|
|
def do_hash_map(ml):
|
|
|
|
return types._hash_mapl(ml.values)
|
|
|
|
|
|
|
|
def hash_map_Q(args):
|
|
|
|
return wrap_tf(types._hash_map_Q(args[0]))
|
|
|
|
|
|
|
|
def assoc(args):
|
|
|
|
src_hm, key_vals = args[0], args.rest()
|
|
|
|
new_dct = src_hm.dct.copy()
|
|
|
|
for i in range(0,len(key_vals),2):
|
|
|
|
k = key_vals[i]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(k, MalStr):
|
|
|
|
throw_str("assoc called with non-string/non-keyword key")
|
2015-06-11 05:59:01 +03:00
|
|
|
new_dct[k.value] = key_vals[i+1]
|
|
|
|
return MalHashMap(new_dct)
|
|
|
|
|
|
|
|
def dissoc(args):
|
|
|
|
src_hm, keys = args[0], args.rest()
|
|
|
|
new_dct = src_hm.dct.copy()
|
|
|
|
for k in keys.values:
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(k, MalStr):
|
|
|
|
throw_str("dissoc called with non-string/non-keyword key")
|
2015-06-11 05:59:01 +03:00
|
|
|
if k.value in new_dct:
|
|
|
|
del new_dct[k.value]
|
|
|
|
return MalHashMap(new_dct)
|
|
|
|
|
|
|
|
def get(args):
|
|
|
|
obj, key = args[0], args[1]
|
|
|
|
if obj is nil:
|
|
|
|
return nil
|
|
|
|
elif isinstance(obj, MalHashMap):
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(key, MalStr):
|
|
|
|
throw_str("get called on hash-map with non-string/non-keyword key")
|
2015-06-11 05:59:01 +03:00
|
|
|
if obj and key.value in obj.dct:
|
|
|
|
return obj.dct[key.value]
|
|
|
|
else:
|
|
|
|
return nil
|
|
|
|
elif isinstance(obj, MalList):
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(key, MalInt):
|
|
|
|
throw_str("get called on list/vector with non-string/non-keyword key")
|
2015-06-11 05:59:01 +03:00
|
|
|
return obj.values[key.value]
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("get called on invalid type")
|
2015-06-11 05:59:01 +03:00
|
|
|
|
|
|
|
def contains_Q(args):
|
|
|
|
hm, key = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(key, MalStr):
|
|
|
|
throw_str("contains? called on hash-map with non-string/non-keyword key")
|
2015-06-11 05:59:01 +03:00
|
|
|
return wrap_tf(key.value in hm.dct)
|
|
|
|
|
|
|
|
def keys(args):
|
|
|
|
hm = args[0]
|
|
|
|
keys = []
|
|
|
|
for k in hm.dct.keys(): keys.append(MalStr(k))
|
|
|
|
return MalList(keys)
|
|
|
|
|
|
|
|
def vals(args):
|
|
|
|
hm = args[0]
|
|
|
|
return MalList(hm.dct.values())
|
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
# Sequence functions
|
|
|
|
def do_list(ml):
|
|
|
|
return ml
|
|
|
|
|
|
|
|
def list_Q(args):
|
2015-06-11 05:59:01 +03:00
|
|
|
return wrap_tf(types._list_Q(args[0]))
|
|
|
|
|
|
|
|
def do_vector(ml):
|
|
|
|
return MalVector(ml.values)
|
|
|
|
|
|
|
|
def vector_Q(args):
|
|
|
|
return wrap_tf(types._vector_Q(args[0]))
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
def empty_Q(args):
|
|
|
|
seq = args[0]
|
|
|
|
if isinstance(seq, MalList):
|
2015-06-10 07:07:03 +03:00
|
|
|
return wrap_tf(len(seq) == 0)
|
2015-06-09 05:58:37 +03:00
|
|
|
elif seq is nil:
|
|
|
|
return true
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("empty? called on non-sequence")
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
def count(args):
|
|
|
|
seq = args[0]
|
|
|
|
if isinstance(seq, MalList):
|
|
|
|
return MalInt(len(seq))
|
|
|
|
elif seq is nil:
|
|
|
|
return MalInt(0)
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("count called on non-sequence")
|
2015-06-09 05:58:37 +03:00
|
|
|
|
2015-06-11 05:59:01 +03:00
|
|
|
def sequential_Q(args):
|
|
|
|
return wrap_tf(types._sequential_Q(args[0]))
|
|
|
|
|
2015-06-09 07:38:56 +03:00
|
|
|
def cons(args):
|
|
|
|
x, seq = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(seq, MalList):
|
|
|
|
throw_str("cons called with non-list/non-vector")
|
2015-06-09 07:38:56 +03:00
|
|
|
return MalList([x] + seq.values)
|
|
|
|
|
|
|
|
def concat(args):
|
|
|
|
new_lst = []
|
|
|
|
for l in args.values:
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(l, MalList):
|
|
|
|
throw_str("concat called with non-list/non-vector")
|
2015-06-09 07:38:56 +03:00
|
|
|
new_lst = new_lst + l.values
|
|
|
|
return MalList(new_lst)
|
|
|
|
|
2015-06-10 05:21:12 +03:00
|
|
|
def nth(args):
|
|
|
|
lst, idx = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(lst, MalList):
|
|
|
|
throw_str("nth called with non-list/non-vector")
|
|
|
|
if not isinstance(idx, MalInt):
|
|
|
|
throw_str("nth called with non-int index")
|
2015-06-10 05:21:12 +03:00
|
|
|
if idx.value < len(lst): return lst[idx.value]
|
2015-06-11 08:15:07 +03:00
|
|
|
else: throw_str("nth: index out of range")
|
2015-06-10 05:21:12 +03:00
|
|
|
|
|
|
|
def first(args):
|
|
|
|
a0 = args[0]
|
2016-02-03 21:22:29 +03:00
|
|
|
if a0 is nil:
|
|
|
|
return nil
|
|
|
|
elif not isinstance(a0, MalList):
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("first called with non-list/non-vector")
|
2015-06-10 05:21:12 +03:00
|
|
|
if len(a0) == 0: return nil
|
|
|
|
else: return a0[0]
|
|
|
|
|
|
|
|
def rest(args):
|
|
|
|
a0 = args[0]
|
2016-02-03 21:22:29 +03:00
|
|
|
if a0 is nil:
|
|
|
|
return MalList([])
|
|
|
|
elif not isinstance(a0, MalList):
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("rest called with non-list/non-vector")
|
2015-06-10 05:21:12 +03:00
|
|
|
if len(a0) == 0: return MalList([])
|
|
|
|
else: return a0.rest()
|
|
|
|
|
2015-06-10 07:07:03 +03:00
|
|
|
def apply(args):
|
|
|
|
f, fargs = args[0], args.rest()
|
|
|
|
last_arg = fargs.values[-1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(last_arg, MalList):
|
|
|
|
throw_str("map called with non-list")
|
2015-06-10 07:07:03 +03:00
|
|
|
all_args = fargs.values[0:-1] + last_arg.values
|
|
|
|
return f.apply(MalList(all_args))
|
|
|
|
|
|
|
|
def mapf(args):
|
|
|
|
f, lst = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(lst, MalList):
|
|
|
|
throw_str("map called with non-list")
|
2015-06-10 07:07:03 +03:00
|
|
|
res = []
|
|
|
|
for a in lst.values:
|
|
|
|
res.append(f.apply(MalList([a])))
|
|
|
|
return MalList(res)
|
|
|
|
|
2016-02-11 18:19:53 +03:00
|
|
|
# retains metadata
|
|
|
|
def conj(args):
|
|
|
|
lst, args = args[0], args.rest()
|
|
|
|
new_lst = None
|
|
|
|
if types._list_Q(lst):
|
|
|
|
vals = args.values[:]
|
|
|
|
vals.reverse()
|
|
|
|
new_lst = MalList(vals + lst.values)
|
|
|
|
elif types._vector_Q(lst):
|
|
|
|
new_lst = MalVector(lst.values + list(args.values))
|
|
|
|
else:
|
|
|
|
throw_str("conj on non-list/non-vector")
|
|
|
|
new_lst.meta = lst.meta
|
|
|
|
return new_lst
|
|
|
|
|
|
|
|
def seq(args):
|
|
|
|
a0 = args[0]
|
|
|
|
if isinstance(a0, MalVector):
|
|
|
|
if len(a0) == 0: return nil
|
|
|
|
return MalList(a0.values)
|
|
|
|
elif isinstance(a0, MalList):
|
|
|
|
if len(a0) == 0: return nil
|
|
|
|
return a0
|
|
|
|
elif types._string_Q(a0):
|
|
|
|
assert isinstance(a0, MalStr)
|
|
|
|
if len(a0) == 0: return nil
|
|
|
|
return MalList([MalStr(unicode(c)) for c in a0.value])
|
|
|
|
elif a0 is nil:
|
|
|
|
return nil
|
|
|
|
else:
|
|
|
|
throw_str("seq: called on non-sequence")
|
2015-06-10 07:07:03 +03:00
|
|
|
|
2015-06-11 07:25:55 +03:00
|
|
|
# Metadata functions
|
|
|
|
def with_meta(args):
|
|
|
|
obj, meta = args[0], args[1]
|
2015-06-11 07:54:18 +03:00
|
|
|
if isinstance(obj, MalMeta):
|
2015-06-11 07:25:55 +03:00
|
|
|
new_obj = types._clone(obj)
|
|
|
|
new_obj.meta = meta
|
|
|
|
return new_obj
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("with-meta not supported on type")
|
2015-06-11 07:25:55 +03:00
|
|
|
|
|
|
|
def meta(args):
|
|
|
|
obj = args[0]
|
2015-06-11 07:54:18 +03:00
|
|
|
if isinstance(obj, MalMeta):
|
2015-06-11 07:25:55 +03:00
|
|
|
return obj.meta
|
|
|
|
else:
|
2015-06-11 08:15:07 +03:00
|
|
|
throw_str("meta not supported on type")
|
2015-06-11 07:25:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
# Atoms functions
|
|
|
|
def do_atom(args):
|
|
|
|
return MalAtom(args[0])
|
|
|
|
def atom_Q(args):
|
|
|
|
return wrap_tf(types._atom_Q(args[0]))
|
|
|
|
def deref(args):
|
|
|
|
atm = args[0]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(atm, MalAtom):
|
|
|
|
throw_str("deref called on non-atom")
|
2015-06-11 07:54:18 +03:00
|
|
|
return atm.value
|
2015-06-11 07:25:55 +03:00
|
|
|
def reset_BANG(args):
|
|
|
|
atm, val = args[0], args[1]
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(atm, MalAtom):
|
|
|
|
throw_str("reset! called on non-atom")
|
2015-06-11 07:54:18 +03:00
|
|
|
atm.value = val
|
|
|
|
return atm.value
|
2015-06-11 07:25:55 +03:00
|
|
|
def swap_BANG(args):
|
|
|
|
atm, f, fargs = args[0], args[1], args.slice(2)
|
2015-06-11 08:15:07 +03:00
|
|
|
if not isinstance(atm, MalAtom):
|
|
|
|
throw_str("swap! called on non-atom")
|
|
|
|
if not isinstance(f, MalFunc):
|
|
|
|
throw_str("swap! called with non-function")
|
2015-06-11 07:54:18 +03:00
|
|
|
all_args = [atm.value] + fargs.values
|
|
|
|
atm.value = f.apply(MalList(all_args))
|
|
|
|
return atm.value
|
2015-06-09 05:58:37 +03:00
|
|
|
|
|
|
|
|
2015-06-11 07:54:18 +03:00
|
|
|
ns = {
|
2015-06-09 05:58:37 +03:00
|
|
|
'=': do_equal,
|
2015-06-10 07:07:03 +03:00
|
|
|
'throw': throw,
|
|
|
|
'nil?': nil_Q,
|
|
|
|
'true?': true_Q,
|
|
|
|
'false?': false_Q,
|
2016-02-11 18:19:53 +03:00
|
|
|
'string?': string_Q,
|
2015-06-10 07:07:03 +03:00
|
|
|
'symbol': symbol,
|
|
|
|
'symbol?': symbol_Q,
|
|
|
|
'keyword': keyword,
|
|
|
|
'keyword?': keyword_Q,
|
2017-10-12 04:18:50 +03:00
|
|
|
'number?': number_Q,
|
|
|
|
'fn?': function_Q,
|
|
|
|
'macro?': macro_Q,
|
2015-06-10 07:07:03 +03:00
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
'pr-str': pr_str,
|
|
|
|
'str': do_str,
|
|
|
|
'prn': prn,
|
|
|
|
'println': println,
|
2015-06-10 07:22:48 +03:00
|
|
|
'readline': do_readline,
|
2015-06-09 07:09:17 +03:00
|
|
|
'read-string': read_str,
|
|
|
|
'slurp': slurp,
|
2015-06-09 05:58:37 +03:00
|
|
|
'<': lt,
|
|
|
|
'<=': lte,
|
|
|
|
'>': gt,
|
|
|
|
'>=': gte,
|
|
|
|
'+': plus,
|
|
|
|
'-': minus,
|
|
|
|
'*': multiply,
|
|
|
|
'/': divide,
|
2015-06-11 07:25:55 +03:00
|
|
|
'time-ms': time_ms,
|
|
|
|
|
2015-06-09 05:58:37 +03:00
|
|
|
'list': do_list,
|
|
|
|
'list?': list_Q,
|
2015-06-11 05:59:01 +03:00
|
|
|
'vector': do_vector,
|
|
|
|
'vector?': vector_Q,
|
|
|
|
'hash-map': do_hash_map,
|
|
|
|
'map?': hash_map_Q,
|
|
|
|
'assoc': assoc,
|
|
|
|
'dissoc': dissoc,
|
|
|
|
'get': get,
|
|
|
|
'contains?': contains_Q,
|
|
|
|
'keys': keys,
|
|
|
|
'vals': vals,
|
|
|
|
|
|
|
|
'sequential?': sequential_Q,
|
2015-06-09 07:38:56 +03:00
|
|
|
'cons': cons,
|
|
|
|
'concat': concat,
|
2015-06-10 05:21:12 +03:00
|
|
|
'nth': nth,
|
|
|
|
'first': first,
|
|
|
|
'rest': rest,
|
2015-06-09 05:58:37 +03:00
|
|
|
'empty?': empty_Q,
|
|
|
|
'count': count,
|
2015-06-10 07:07:03 +03:00
|
|
|
'apply': apply,
|
|
|
|
'map': mapf,
|
2015-06-11 07:25:55 +03:00
|
|
|
|
2016-02-11 18:19:53 +03:00
|
|
|
'conj': conj,
|
|
|
|
'seq': seq,
|
|
|
|
|
2015-06-11 07:25:55 +03:00
|
|
|
'with-meta': with_meta,
|
|
|
|
'meta': meta,
|
|
|
|
'atom': do_atom,
|
|
|
|
'atom?': atom_Q,
|
|
|
|
'deref': deref,
|
|
|
|
'reset!': reset_BANG,
|
|
|
|
'swap!': swap_BANG
|
2015-06-09 05:58:37 +03:00
|
|
|
}
|
|
|
|
|