1
0
mirror of https://github.com/janet-lang/janet synced 2025-03-28 19:16:56 +00:00

Add array and tuple versions of map and for.

This commit is contained in:
Calvin Rose 2018-08-23 11:10:48 -04:00
parent 45f8db0360
commit f5b4bc4fdf
2 changed files with 56 additions and 38 deletions

View File

@ -26,7 +26,7 @@
(def start (fstart 0)) (def start (fstart 0))
(def fnbody (tuple.prepend (tuple.prepend (tuple.slice more start) name) 'fn)) (def fnbody (tuple.prepend (tuple.prepend (tuple.slice more start) name) 'fn))
(def formargs (array.concat @['def name] (array.slice more 0 start) @[fnbody])) (def formargs (array.concat @['def name] (array.slice more 0 start) @[fnbody]))
(apply1 tuple formargs))) (tuple.slice formargs 0)))
(def defmacro :macro (def defmacro :macro
"Define a macro." "Define a macro."
@ -36,17 +36,17 @@
(defmacro defmacro- (defmacro defmacro-
"Define a private macro that will not be exported." "Define a private macro that will not be exported."
[name & more] [name & more]
(apply1 tuple (array.concat @['defmacro name :private] more))) (tuple.slice (array.concat @['defmacro name :private] more) 0))
(defmacro defn- (defmacro defn-
"Define a private function that will not be exported." "Define a private function that will not be exported."
[name & more] [name & more]
(apply1 tuple (array.concat @['defn name :private] more))) (tuple.slice (array.concat @['defn name :private] more) 0))
(defmacro def- (defmacro def-
"Define a private value that will not be exported." "Define a private value that will not be exported."
[name & more] [name & more]
(apply1 tuple (array.concat @['def name :private] more))) (tuple.slice (array.concat @['def name :private] more) 0))
(defmacro defasm (defmacro defasm
"Define a function using assembly" "Define a function using assembly"
@ -230,7 +230,7 @@
(array.push accum (tuple 'def k v)) (array.push accum (tuple 'def k v))
(+= i 2)) (+= i 2))
(array.concat accum body) (array.concat accum body)
(apply1 tuple accum)) (tuple.slice accum 0))
(defmacro and (defmacro and
"Evaluates to the last argument if all preceding elements are true, otherwise "Evaluates to the last argument if all preceding elements are true, otherwise
@ -294,7 +294,7 @@
(def subloop (doone (+ i 3) preds)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
(tuple 'var $iter nil) (tuple 'var $iter nil)
(tuple 'while (apply1 tuple preds) (tuple 'while (tuple.slice preds 0)
(tuple 'def bindings $iter) (tuple 'def bindings $iter)
subloop))) subloop)))
:range (do :range (do
@ -307,7 +307,7 @@
(tuple 'do (tuple 'do
(tuple 'var $iter start) (tuple 'var $iter start)
(tuple 'def endsym end) (tuple 'def endsym end)
(tuple 'while (apply1 tuple preds) (tuple 'while (tuple.slice preds 0)
(tuple 'def bindings $iter) (tuple 'def bindings $iter)
subloop subloop
(tuple ':= $iter (tuple + $iter inc))))) (tuple ':= $iter (tuple + $iter inc)))))
@ -319,7 +319,7 @@
(tuple 'do (tuple 'do
(tuple 'def $dict object) (tuple 'def $dict object)
(tuple 'var $iter (tuple next $dict nil)) (tuple 'var $iter (tuple next $dict nil))
(tuple 'while (apply1 tuple preds) (tuple 'while (tuple.slice preds 0)
(tuple 'def bindings $iter) (tuple 'def bindings $iter)
subloop subloop
(tuple ':= $iter (tuple next $dict $iter))))) (tuple ':= $iter (tuple next $dict $iter)))))
@ -333,14 +333,14 @@
(tuple 'def $indexed object) (tuple 'def $indexed object)
(tuple 'def $len (tuple length $indexed)) (tuple 'def $len (tuple length $indexed))
(tuple 'var $i 0) (tuple 'var $i 0)
(tuple 'while (apply1 tuple preds) (tuple 'while (tuple.slice preds 0)
(tuple 'def bindings (tuple get $indexed $i)) (tuple 'def bindings (tuple get $indexed $i))
subloop subloop
(tuple ':= $i (tuple + 1 $i))))) (tuple ':= $i (tuple + 1 $i)))))
(error (string "unexpected loop verb: " verb))))))) (error (string "unexpected loop verb: " verb)))))))
(doone 0 nil)) (doone 0 nil))
(defmacro for (defmacro fora
"Similar to loop, but accumulates the loop body into an array and returns that." "Similar to loop, but accumulates the loop body into an array and returns that."
[head & body] [head & body]
(def $accum (gensym)) (def $accum (gensym))
@ -351,6 +351,17 @@
(tuple.prepend body 'do))) (tuple.prepend body 'do)))
$accum)) $accum))
(defmacro for
"Similar to loop, but accumulates the loop body into a tuple and returns that."
[head & body]
(def $accum (gensym))
(tuple 'do
(tuple 'def $accum @[])
(tuple 'loop head
(tuple array.push $accum
(tuple.prepend body 'do)))
(tuple tuple.slice $accum 0)))
(defn sum [xs] (defn sum [xs]
(var accum 0) (var accum 0)
(loop [x :in xs] (+= accum x)) (loop [x :in xs] (+= accum x))
@ -482,10 +493,10 @@
(defn sorted (defn sorted
"Returns the sorted version of an indexed data structure." "Returns the sorted version of an indexed data structure."
@[ind by] @[ind by t]
(def sa (sort (apply1 array ind) by)) (def sa (sort (array.slice ind 0) by))
(if (= :tuple (type ind)) (if (= :tuple (or t (type ind)))
(apply1 tuple sa) (tuple.slice sa 0)
sa)) sa))
(defn reduce (defn reduce
@ -497,9 +508,9 @@
(:= res (f res x))) (:= res (f res x)))
res) res)
(defn map (defn mapa
"Map a function over every element in an array or tuple and return "Map a function over every element in an indexed data structure and
the same type as the input sequence." return an array of the results."
[f & inds] [f & inds]
(def ninds (length inds)) (def ninds (length inds))
(if (= 0 ninds) (error "expected at least 1 indexed collection")) (if (= 0 ninds) (error "expected at least 1 indexed collection"))
@ -520,6 +531,12 @@
(put res i (apply1 f args)))) (put res i (apply1 f args))))
res) res)
(defn map
"Map a function over every element in an indexed data structure and
return a tuple of the results."
[f & inds]
(tuple.slice (apply mapa f inds) 0))
(defn each (defn each
"Map a function over every element in an array or tuple but do not "Map a function over every element in an array or tuple but do not
return a new indexed type." return a new indexed type."
@ -543,26 +560,27 @@
(defn mapcat (defn mapcat
"Map a function over every element in an array or tuple and "Map a function over every element in an array or tuple and
use array to concatenate the results. Returns the same use array to concatenate the results. Returns the type given
type as the input sequence." as the third argument, or same type as the input indexed structure."
@[f ind t] @[f ind t]
(def res @[]) (def res @[])
(loop [x :in ind] (loop [x :in ind]
(array.concat res (f x))) (array.concat res (f x)))
(if (= :tuple (type (or t ind))) (if (= :tuple (or t (type ind)))
(apply1 tuple res) (tuple.slice res 0)
res)) res))
(defn filter (defn filter
"Given a predicate, take only elements from an array or tuple for "Given a predicate, take only elements from an array or tuple for
which (pred element) is truthy. Returns the same type as the input sequence." which (pred element) is truthy. Returns the type given as the
third argument, or the same type as the input indexed structure."
@[pred ind t] @[pred ind t]
(def res @[]) (def res @[])
(loop [item :in ind] (loop [item :in ind]
(if (pred item) (if (pred item)
(array.push res item))) (array.push res item)))
(if (= :tuple (type (or t ind))) (if (= :tuple (or t (type ind)))
(apply1 tuple res) (tuple.slice res 0)
res)) res))
(defn range (defn range
@ -618,7 +636,7 @@
the predicate, and abort on first failure. Returns a new tuple." the predicate, and abort on first failure. Returns a new tuple."
[pred ind] [pred ind]
(def i (find-index pred ind)) (def i (find-index pred ind))
(tuple.slice ind i -1)) (tuple.slice ind i))
(defn drop-while (defn drop-while
"Same as (drop-until (complement pred) ind)." "Same as (drop-until (complement pred) ind)."
@ -631,7 +649,7 @@
(def ret @[]) (def ret @[])
(loop [f :in funs] (loop [f :in funs]
(array.push ret (apply1 f args))) (array.push ret (apply1 f args)))
(apply1 tuple ret))) (tuple.slice ret 0)))
(defmacro juxt (defmacro juxt
[& funs] [& funs]
@ -639,7 +657,7 @@
(def $args (gensym)) (def $args (gensym))
(loop [f :in funs] (loop [f :in funs]
(array.push parts (tuple apply1 f $args))) (array.push parts (tuple apply1 f $args)))
(tuple 'fn (tuple '& $args) (apply1 tuple parts))) (tuple 'fn (tuple '& $args) (tuple.slice parts 0)))
(defmacro -> (defmacro ->
"Threading macro. Inserts x as the second value in the first form "Threading macro. Inserts x as the second value in the first form
@ -651,7 +669,7 @@
[tuple (get n 0) (array.slice n 1)] [tuple (get n 0) (array.slice n 1)]
[tuple n @[]])) [tuple n @[]]))
(def parts (array.concat @[h last] t)) (def parts (array.concat @[h last] t))
(apply1 tuple parts)) (tuple.slice parts 0))
(reduce fop x forms)) (reduce fop x forms))
(defmacro ->> (defmacro ->>
@ -664,7 +682,7 @@
[tuple (get n 0) (array.slice n 1)] [tuple (get n 0) (array.slice n 1)]
[tuple n @[]])) [tuple n @[]]))
(def parts (array.concat @[h] t @[last])) (def parts (array.concat @[h] t @[last]))
(apply1 tuple parts)) (tuple.slice parts 0))
(reduce fop x forms)) (reduce fop x forms))
(defn partial (defn partial
@ -697,7 +715,7 @@
(defn tuple.reverse (defn tuple.reverse
"Reverses the order of the elements given an array or tuple and returns a tuple" "Reverses the order of the elements given an array or tuple and returns a tuple"
[t] [t]
(apply1 tuple (array.reverse t))) (tuple.slice (array.reverse t) 0))
(defn reverse (defn reverse
"Reverses order of elements in a given array or tuple" "Reverses order of elements in a given array or tuple"
@ -889,7 +907,7 @@
(defn expand-bindings [x] (defn expand-bindings [x]
(case (type x) (case (type x)
:array (map expand-bindings x) :array (map expand-bindings x)
:tuple (apply1 tuple (map expand-bindings x)) :tuple (tuple.slice (map expand-bindings x) 0)
:table (dotable x expand-bindings) :table (dotable x expand-bindings)
:struct (table.to-struct (dotable x expand-bindings)) :struct (table.to-struct (dotable x expand-bindings))
(macroexpand-1 x))) (macroexpand-1 x)))
@ -898,8 +916,8 @@
(def len (length t)) (def len (length t))
(def last (get t (- len 1))) (def last (get t (- len 1)))
(def last2 (get t (- len 2))) (def last2 (get t (- len 2)))
(apply1 tuple (array.concat (array.slice t 0 -3) (tuple.slice (array.concat (array.slice t 0 -3)
@[(expand-bindings last2) (macroexpand-1 last)]))) @[(expand-bindings last2) (macroexpand-1 last)]) 0))
(defn expandall [t] (defn expandall [t]
(def args (map macroexpand-1 (tuple.slice t 1))) (def args (map macroexpand-1 (tuple.slice t 1)))
@ -928,7 +946,7 @@
(cond (cond
s (s t) s (s t)
m? (apply1 m (tuple.slice t 1)) m? (apply1 m (tuple.slice t 1))
(apply1 tuple (map macroexpand-1 t)))) (tuple.slice (map macroexpand-1 t) 0)))
(def ret (def ret
(case (type x) (case (type x)
@ -1166,7 +1184,7 @@
(def last (get parts (- (length parts) 1))) (def last (get parts (- (length parts) 1)))
(def normname (string.replace-all "." "/" path)) (def normname (string.replace-all "." "/" path))
(array.push (array.push
(map (fn [x] (mapa (fn [x]
(def y (string.replace "??" last x)) (def y (string.replace "??" last x))
(string.replace "?" normname y)) (string.replace "?" normname y))
paths) paths)

View File

@ -164,11 +164,11 @@
(testmarsh (fn name [x] x) "marshal function 1") (testmarsh (fn name [x] x) "marshal function 1")
(testmarsh (fn [x] (+ 10 x 2)) "marshal function 2") (testmarsh (fn [x] (+ 10 x 2)) "marshal function 2")
(testmarsh (fn thing [x] (+ 11 x x 30)) "marshal function 3") (testmarsh (fn thing [x] (+ 11 x x 30)) "marshal function 3")
(testmarsh map "marshal function 4") (testmarsh mapa "marshal function 4")
(testmarsh reduce "marshal function 4") (testmarsh reduce "marshal function 5")
# Large functions # Large functions
(def manydefs (for [i :range [0 300]] (tuple 'def (gensym) (string "value_" i)))) (def manydefs (fora [i :range [0 300]] (tuple 'def (gensym) (string "value_" i))))
(array.push manydefs (tuple * 10000 3 5 7 9)) (array.push manydefs (tuple * 10000 3 5 7 9))
(def f (compile (tuple.prepend manydefs 'do) *env*)) (def f (compile (tuple.prepend manydefs 'do) *env*))
(assert (= (f) (* 10000 3 5 7 9)) "long function compilation") (assert (= (f) (* 10000 3 5 7 9)) "long function compilation")