1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-28 16:13:16 +00:00

Add some forms ported from clojure/walk

Add as-> and as?-> macros.
This commit is contained in:
Calvin Rose 2018-12-23 19:00:16 -05:00
parent 876a68f620
commit 70b4c8ae84

View File

@ -797,6 +797,64 @@
~(let [,sym ,last] (if ,sym ,(tuple/slice parts 0))))
(reduce fop x forms))
(defn walk
"Iterate over the values in ast and apply f
to them. Collect the results in a data structure . If ast is not a
table, struct, array, or tuple,
behaves as the identity function."
[f form]
(defn walk-ind []
(def ret @[])
(each x form (array/push ret (f x)))
ret)
(defn walk-dict []
(def ret @[])
(loop [k :keys form]
(array/push ret (f k) (f form.k)))
ret)
(case (type form)
:table (table ;(walk-dict))
:struct (struct ;(walk-dict))
:array (walk-ind)
:tuple (tuple ;(walk-ind))
form))
(defn post-walk
"Do a post-order traversal of a data sructure and call (f x)
on every visitation."
[f form]
(f (walk (fn [x] (post-walk f x)) form)))
(defn pre-walk
"Similar to post-walk, but do pre-order traversal."
[f form]
(walk (fn [x] (pre-walk f x)) (f form)))
(defmacro as->
"Thread forms together, replacing as in forms with the value
of the previous form. The first for is the value x. Returns the
last value."
[x as & forms]
(var prev x)
(loop [form :in forms]
(def sym (gensym))
(def next-prev (post-walk (fn [y] (if (= y as) sym y)) form))
(set prev ~(let [,sym ,prev] ,next-prev)))
prev)
(defmacro as?->
"Thread forms together, replacing as in forms with the value
of the previous form. The first for is the value x. If any
intermediate values are falsey, return nil; otherwise, returns the
last value."
[x as & forms]
(var prev x)
(loop [form :in forms]
(def sym (gensym))
(def next-prev (post-walk (fn [y] (if (= y as) sym y)) form))
(set prev ~(if-let [,sym ,prev] ,next-prev)))
prev)
(defn partial
"Partial function application."
[f & more]