Update:
Updated most methods to replace While with For, and added tons of new tests for things like (cycle []) and lists with None's in them. thanks @olasd Add set of new core functions Add set of new core functions to the stdlib. Moved the auto-import code from compile_expression to HySymbol so that "even?' in this style expression will be found and imported. (list (filter even? [1 2 3 4 5])) The core functions are documented in 2 sections, one for basic functions like (even?..) and (nth ...) and one for all the sequence functions. Update: This removes all the caching decorators, misnamed as 'lazy-seq' from the core. All sequence methods now just use yield to return a generator, so they are Python-lazy Further refinements of core functions Cleaned up the docs to use 'iterator' instead of 'generator' Fixed drop to just return the iterator instead of an extra yield loop. But also added a test to catch dropping too many.
This commit is contained in:
parent
e138af8b94
commit
41ae4f4d2c
@ -3,33 +3,38 @@
|
|||||||
;;;;
|
;;;;
|
||||||
|
|
||||||
|
|
||||||
|
(defn _numeric-check [x]
|
||||||
|
(if (not (numeric? x))
|
||||||
|
(raise (TypeError (.format "{0!r} is not a number" x)))))
|
||||||
|
|
||||||
(defn cycle [coll]
|
(defn cycle [coll]
|
||||||
"Yield an infinite repetition of the items in coll"
|
"Yield an infinite repetition of the items in coll"
|
||||||
(while true
|
(setv seen [])
|
||||||
(for [x coll]
|
(for [x coll]
|
||||||
|
(yield x)
|
||||||
|
(.append seen x))
|
||||||
|
(while seen
|
||||||
|
(for [x seen]
|
||||||
(yield x))))
|
(yield x))))
|
||||||
|
|
||||||
(defn dec [n]
|
(defn dec [n]
|
||||||
"Decrement n by 1"
|
"Decrement n by 1"
|
||||||
|
(_numeric-check n)
|
||||||
(- n 1))
|
(- n 1))
|
||||||
|
|
||||||
(defn distinct [coll]
|
(defn distinct [coll]
|
||||||
"Return a generator from the original collection with duplicates
|
"Return a generator from the original collection with duplicates
|
||||||
removed"
|
removed"
|
||||||
(let [ [seen [] ]
|
(let [[seen []] [citer (iter coll)]]
|
||||||
[citer (iter coll)]
|
(for [val citer]
|
||||||
[val (next citer)] ]
|
|
||||||
(while (not (none? val))
|
|
||||||
(do
|
|
||||||
(if (not_in val seen)
|
(if (not_in val seen)
|
||||||
(do
|
(do
|
||||||
(yield val)
|
(yield val)
|
||||||
(.append seen val)))
|
(.append seen val))))))
|
||||||
(setv val (next citer))))))
|
|
||||||
|
|
||||||
(defn drop [count coll]
|
(defn drop [count coll]
|
||||||
"Drop `count` elements from `coll` and yield back the rest"
|
"Drop `count` elements from `coll` and yield back the rest"
|
||||||
(let [ [citer (iter coll)] ]
|
(let [[citer (iter coll)]]
|
||||||
(try (for [i (range count)]
|
(try (for [i (range count)]
|
||||||
(next citer))
|
(next citer))
|
||||||
(catch [StopIteration]))
|
(catch [StopIteration]))
|
||||||
@ -37,18 +42,19 @@
|
|||||||
|
|
||||||
(defn even? [n]
|
(defn even? [n]
|
||||||
"Return true if n is an even number"
|
"Return true if n is an even number"
|
||||||
|
(_numeric-check n)
|
||||||
(= (% n 2) 0))
|
(= (% n 2) 0))
|
||||||
|
|
||||||
(defn filter [pred coll]
|
(defn filter [pred coll]
|
||||||
"Return all elements from coll that pass filter"
|
"Return all elements from `coll` that pass `pred`"
|
||||||
(let [ [citer (iter coll)] [val (next citer)] ]
|
(let [[citer (iter coll)]]
|
||||||
(while (not (none? val))
|
(for [val citer]
|
||||||
(if (pred val)
|
(if (pred val)
|
||||||
(yield val))
|
(yield val)))))
|
||||||
(setv val (next citer)))))
|
|
||||||
|
|
||||||
(defn inc [n]
|
(defn inc [n]
|
||||||
"Increment n by 1"
|
"Increment n by 1"
|
||||||
|
(_numeric-check n)
|
||||||
(+ n 1))
|
(+ n 1))
|
||||||
|
|
||||||
(defn instance? [klass x]
|
(defn instance? [klass x]
|
||||||
@ -72,12 +78,17 @@
|
|||||||
|
|
||||||
(defn neg? [n]
|
(defn neg? [n]
|
||||||
"Return true if n is < 0"
|
"Return true if n is < 0"
|
||||||
|
(_numeric-check n)
|
||||||
(< n 0))
|
(< n 0))
|
||||||
|
|
||||||
(defn none? [x]
|
(defn none? [x]
|
||||||
"Return true if x is None"
|
"Return true if x is None"
|
||||||
(is x None))
|
(is x None))
|
||||||
|
|
||||||
|
(defn numeric? [x]
|
||||||
|
(import numbers)
|
||||||
|
(instance? numbers.Number x))
|
||||||
|
|
||||||
(defn nth [coll index]
|
(defn nth [coll index]
|
||||||
"Return nth item in collection or sequence, counting from 0"
|
"Return nth item in collection or sequence, counting from 0"
|
||||||
(if (not (neg? index))
|
(if (not (neg? index))
|
||||||
@ -90,19 +101,20 @@
|
|||||||
|
|
||||||
(defn odd? [n]
|
(defn odd? [n]
|
||||||
"Return true if n is an odd number"
|
"Return true if n is an odd number"
|
||||||
|
(_numeric-check n)
|
||||||
(= (% n 2) 1))
|
(= (% n 2) 1))
|
||||||
|
|
||||||
(defn pos? [n]
|
(defn pos? [n]
|
||||||
"Return true if n is > 0"
|
"Return true if n is > 0"
|
||||||
|
(_numeric_check n)
|
||||||
(> n 0))
|
(> n 0))
|
||||||
|
|
||||||
(defn remove [pred coll]
|
(defn remove [pred coll]
|
||||||
"Return coll with elements removed that pass `pred`"
|
"Return coll with elements removed that pass `pred`"
|
||||||
(let [ [citer (iter coll)] [val (next citer)] ]
|
(let [[citer (iter coll)]]
|
||||||
(while (not (none? val))
|
(for [val citer]
|
||||||
(if (not (pred val))
|
(if (not (pred val))
|
||||||
(yield val))
|
(yield val)))))
|
||||||
(setv val (next citer)))))
|
|
||||||
|
|
||||||
(defn repeat [x &optional n]
|
(defn repeat [x &optional n]
|
||||||
"Yield x forever or optionally n times"
|
"Yield x forever or optionally n times"
|
||||||
@ -116,33 +128,33 @@
|
|||||||
(while true
|
(while true
|
||||||
(yield (func))))
|
(yield (func))))
|
||||||
|
|
||||||
(defn take [count what]
|
(defn take [count coll]
|
||||||
"Take `count` elements from `what`, or the whole set if the total
|
"Take `count` elements from `coll`, or the whole set if the total
|
||||||
number of entries in `what` is less than `count`."
|
number of entries in `coll` is less than `count`."
|
||||||
(setv what (iter what))
|
(let [[citer (iter coll)]]
|
||||||
(for [i (range count)]
|
(for [_ (range count)]
|
||||||
(yield (next what))))
|
(yield (next citer)))))
|
||||||
|
|
||||||
(defn take-nth [n coll]
|
(defn take-nth [n coll]
|
||||||
"Return every nth member of coll
|
"Return every nth member of coll
|
||||||
raises ValueError for (not (pos? n))"
|
raises ValueError for (not (pos? n))"
|
||||||
(if (pos? n)
|
(if (pos? n)
|
||||||
(let [ [citer (iter coll)] [val (next citer)] ]
|
(let [[citer (iter coll)] [skip (dec n)]]
|
||||||
(while (not (none? val))
|
(for [val citer]
|
||||||
(yield val)
|
(yield val)
|
||||||
(for [_ (range (dec n))]
|
(for [_ (range skip)]
|
||||||
(next citer))
|
(next citer))))
|
||||||
(setv val (next citer))))
|
|
||||||
(raise (ValueError "n must be positive"))))
|
(raise (ValueError "n must be positive"))))
|
||||||
|
|
||||||
(defn take-while [pred coll]
|
(defn take-while [pred coll]
|
||||||
"Take all elements while `pred` is true"
|
"Take all elements while `pred` is true"
|
||||||
(let [ [citer (iter coll)] [val (next citer)] ]
|
(let [[citer (iter coll)]]
|
||||||
(while (pred val)
|
(for [val citer]
|
||||||
|
(if (pred val)
|
||||||
(yield val)
|
(yield val)
|
||||||
(setv val (next citer)))))
|
(break)))))
|
||||||
|
|
||||||
(def *exports* ["cycle" "dec" "distinct" "drop" "even?" "filter" "inc"
|
(def *exports* ["cycle" "dec" "distinct" "drop" "even?" "filter" "inc"
|
||||||
"instance?" "iterable?" "iterate" "iterator?" "neg?"
|
"instance?" "iterable?" "iterate" "iterator?" "neg?"
|
||||||
"none?" "nth" "odd?" "pos?" "remove" "repeat" "repeatedly"
|
"none?" "nth" "numeric?" "odd?" "pos?" "remove" "repeat"
|
||||||
"take" "take_nth" "take_while"])
|
"repeatedly" "take" "take_nth" "take_while"])
|
||||||
|
@ -13,14 +13,22 @@
|
|||||||
|
|
||||||
(defn test-cycle []
|
(defn test-cycle []
|
||||||
"NATIVE: testing cycle"
|
"NATIVE: testing cycle"
|
||||||
|
(assert-equal (list (cycle [])) [])
|
||||||
(assert-equal (list (take 7 (cycle [1 2 3]))) [1 2 3 1 2 3 1])
|
(assert-equal (list (take 7 (cycle [1 2 3]))) [1 2 3 1 2 3 1])
|
||||||
(assert-equal (list (take 2 (cycle [1 2 3]))) [1 2]))
|
(assert-equal (list (take 2 (cycle [1 2 3]))) [1 2])
|
||||||
|
(assert-equal (list (take 4 (cycle [1 None 3]))) [1 None 3 1]))
|
||||||
|
|
||||||
(defn test-dec []
|
(defn test-dec []
|
||||||
"NATIVE: testing the dec function"
|
"NATIVE: testing the dec function"
|
||||||
(assert-equal 0 (dec 1))
|
(assert-equal 0 (dec 1))
|
||||||
(assert-equal -1 (dec 0))
|
(assert-equal -1 (dec 0))
|
||||||
(assert-equal 0 (dec (dec 2))))
|
(assert-equal 0 (dec (dec 2)))
|
||||||
|
(try (do (dec "foo") (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (dec []) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (dec None) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-distinct []
|
(defn test-distinct []
|
||||||
"NATIVE: testing the distinct function"
|
"NATIVE: testing the distinct function"
|
||||||
@ -32,14 +40,19 @@
|
|||||||
;; now with an iter
|
;; now with an iter
|
||||||
(setv test_iter (iter [1 2 3 4 3 5 2]))
|
(setv test_iter (iter [1 2 3 4 3 5 2]))
|
||||||
(setv res (list (distinct test_iter)))
|
(setv res (list (distinct test_iter)))
|
||||||
(assert-equal res [1 2 3 4 5]))
|
(assert-equal res [1 2 3 4 5])
|
||||||
|
; make sure we can handle None in the list
|
||||||
|
(setv res (list (distinct [1 2 3 2 5 None 3 4 None])))
|
||||||
|
(assert-equal res [1 2 3 5 None 4]))
|
||||||
|
|
||||||
(defn test-drop []
|
(defn test-drop []
|
||||||
"NATIVE: testing drop function"
|
"NATIVE: testing drop function"
|
||||||
(setv res (list (drop 2 [1 2 3 4 5])))
|
(setv res (list (drop 2 [1 2 3 4 5])))
|
||||||
(assert-equal res [ 3 4 5])
|
(assert-equal res [3 4 5])
|
||||||
(setv res (list (drop 3 (iter [1 2 3 4 5]))))
|
(setv res (list (drop 3 (iter [1 2 3 4 5]))))
|
||||||
(assert-equal res [ 4 5])
|
(assert-equal res [4 5])
|
||||||
|
(setv res (list (drop 3 (iter [1 2 3 None 4 5]))))
|
||||||
|
(assert-equal res [None 4 5])
|
||||||
(setv res (list (drop 0 [1 2 3 4 5])))
|
(setv res (list (drop 0 [1 2 3 4 5])))
|
||||||
(assert-equal res [1 2 3 4 5])
|
(assert-equal res [1 2 3 4 5])
|
||||||
(setv res (list (drop -1 [1 2 3 4 5])))
|
(setv res (list (drop -1 [1 2 3 4 5])))
|
||||||
@ -53,7 +66,13 @@
|
|||||||
"NATIVE: testing the even? function"
|
"NATIVE: testing the even? function"
|
||||||
(assert-true (even? -2))
|
(assert-true (even? -2))
|
||||||
(assert-false (even? 1))
|
(assert-false (even? 1))
|
||||||
(assert-true (even? 0)))
|
(assert-true (even? 0))
|
||||||
|
(try (even? "foo")
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (even? [])
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (even? None)
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-filter []
|
(defn test-filter []
|
||||||
"NATIVE: testing the filter function"
|
"NATIVE: testing the filter function"
|
||||||
@ -63,12 +82,26 @@
|
|||||||
(setv res (list (filter pos? (iter [ 1 2 3 -4 5 -6]))))
|
(setv res (list (filter pos? (iter [ 1 2 3 -4 5 -6]))))
|
||||||
(assert-equal res [ 1 2 3 5])
|
(assert-equal res [ 1 2 3 5])
|
||||||
(setv res (list (filter neg? [ -1 -4 5 3 4])))
|
(setv res (list (filter neg? [ -1 -4 5 3 4])))
|
||||||
(assert-false (= res [1 2])))
|
(assert-false (= res [1 2]))
|
||||||
|
;; test with empty list
|
||||||
|
(setv res (list (filter neg? [])))
|
||||||
|
(assert-equal res [])
|
||||||
|
;; test with None in the list
|
||||||
|
(setv res (list (filter even? (filter numeric? [1 2 None 3 4 None 4 6]))))
|
||||||
|
(assert-equal res [2 4 4 6])
|
||||||
|
(setv res (list (filter none? [1 2 None 3 4 None 4 6])))
|
||||||
|
(assert-equal res [None None]))
|
||||||
|
|
||||||
(defn test-inc []
|
(defn test-inc []
|
||||||
"NATIVE: testing the inc function"
|
"NATIVE: testing the inc function"
|
||||||
(assert-equal 3 (inc 2))
|
(assert-equal 3 (inc 2))
|
||||||
(assert-equal 0 (inc -1)))
|
(assert-equal 0 (inc -1))
|
||||||
|
(try (do (inc "foo") (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (inc []) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (inc None) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-instance []
|
(defn test-instance []
|
||||||
"NATIVE: testing instance? function"
|
"NATIVE: testing instance? function"
|
||||||
@ -140,7 +173,13 @@
|
|||||||
"NATIVE: testing the neg? function"
|
"NATIVE: testing the neg? function"
|
||||||
(assert-true (neg? -2))
|
(assert-true (neg? -2))
|
||||||
(assert-false (neg? 1))
|
(assert-false (neg? 1))
|
||||||
(assert-false (neg? 0)))
|
(assert-false (neg? 0))
|
||||||
|
(try (do (neg? "foo") (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (neg? []) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (neg? None) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-none []
|
(defn test-none []
|
||||||
"NATIVE: testing for `is None`"
|
"NATIVE: testing for `is None`"
|
||||||
@ -166,13 +205,25 @@
|
|||||||
"NATIVE: testing the odd? function"
|
"NATIVE: testing the odd? function"
|
||||||
(assert-true (odd? -3))
|
(assert-true (odd? -3))
|
||||||
(assert-true (odd? 1))
|
(assert-true (odd? 1))
|
||||||
(assert-false (odd? 0)))
|
(assert-false (odd? 0))
|
||||||
|
(try (do (odd? "foo") (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (odd? []) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (odd? None) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-pos []
|
(defn test-pos []
|
||||||
"NATIVE: testing the pos? function"
|
"NATIVE: testing the pos? function"
|
||||||
(assert-true (pos? 2))
|
(assert-true (pos? 2))
|
||||||
(assert-false (pos? -1))
|
(assert-false (pos? -1))
|
||||||
(assert-false (pos? 0)))
|
(assert-false (pos? 0))
|
||||||
|
(try (do (pos? "foo") (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (pos? []) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e)))))
|
||||||
|
(try (do (pos? None) (assert False))
|
||||||
|
(catch [e [TypeError]] (assert (in "not a number" (str e))))))
|
||||||
|
|
||||||
(defn test-remove []
|
(defn test-remove []
|
||||||
"NATIVE: testing the remove function"
|
"NATIVE: testing the remove function"
|
||||||
@ -180,7 +231,9 @@
|
|||||||
(assert-equal r [2 4 6])
|
(assert-equal r [2 4 6])
|
||||||
(assert-equal (list (remove even? [1 2 3 4 5])) [1 3 5])
|
(assert-equal (list (remove even? [1 2 3 4 5])) [1 3 5])
|
||||||
(assert-equal (list (remove neg? [1 2 3 4 5])) [1 2 3 4 5])
|
(assert-equal (list (remove neg? [1 2 3 4 5])) [1 2 3 4 5])
|
||||||
(assert-equal (list (remove pos? [1 2 3 4 5])) []))
|
(assert-equal (list (remove pos? [1 2 3 4 5])) [])
|
||||||
|
;; deal with embedded None
|
||||||
|
(assert-equal (list (remove (fn [x] (not (numeric? x))) [1 2 None 3 None 4])) [1 2 3 4]))
|
||||||
|
|
||||||
(defn test-repeat []
|
(defn test-repeat []
|
||||||
"NATIVE: testing repeat"
|
"NATIVE: testing repeat"
|
||||||
@ -206,7 +259,9 @@
|
|||||||
(setv res (list (take 0 (repeat "s"))))
|
(setv res (list (take 0 (repeat "s"))))
|
||||||
(assert-equal res [])
|
(assert-equal res [])
|
||||||
(setv res (list (take -1 (repeat "s"))))
|
(setv res (list (take -1 (repeat "s"))))
|
||||||
(assert-equal res []))
|
(assert-equal res [])
|
||||||
|
(setv res (list (take 6 [1 2 None 4])))
|
||||||
|
(assert-equal res [1 2 None 4]))
|
||||||
|
|
||||||
(defn test-take-nth []
|
(defn test-take-nth []
|
||||||
"NATIVE: testing the take-nth function"
|
"NATIVE: testing the take-nth function"
|
||||||
@ -222,6 +277,11 @@
|
|||||||
(assert-equal res [1 7])
|
(assert-equal res [1 7])
|
||||||
(setv res (list (take-nth 7 [1 2 3 4 5 6 7])))
|
(setv res (list (take-nth 7 [1 2 3 4 5 6 7])))
|
||||||
(assert-equal res [1])
|
(assert-equal res [1])
|
||||||
|
;; what if there are None's in list
|
||||||
|
(setv res (list (take-nth 2 [1 2 3 None 5 6])))
|
||||||
|
(assert-equal res [1 3 5])
|
||||||
|
(setv res (list (take-nth 3 [1 2 3 None 5 6])))
|
||||||
|
(assert-equal res [1 None])
|
||||||
;; using 0 should raise ValueError
|
;; using 0 should raise ValueError
|
||||||
(let [[passed false]]
|
(let [[passed false]]
|
||||||
(try
|
(try
|
||||||
@ -232,6 +292,10 @@
|
|||||||
(defn test-take-while []
|
(defn test-take-while []
|
||||||
"NATIVE: testing the take-while function"
|
"NATIVE: testing the take-while function"
|
||||||
(setv res (list (take-while pos? [ 1 2 3 -4 5])))
|
(setv res (list (take-while pos? [ 1 2 3 -4 5])))
|
||||||
(assert-equal res [ 1 2 3 ])
|
(assert-equal res [1 2 3])
|
||||||
(setv res (list (take-while neg? [ -1 -4 5 3 4])))
|
(setv res (list (take-while neg? [ -1 -4 5 3 4])))
|
||||||
(assert-false (= res [1 2])))
|
(assert-false (= res [1 2]))
|
||||||
|
(setv res (list (take-while none? [None None 1 2 3])))
|
||||||
|
(assert-equal res [None None])
|
||||||
|
(setv res (list (take-while (fn [x] (not (none? x))) [1 2 3 4 None 5 6 None 7])))
|
||||||
|
(assert-equal res [1 2 3 4]))
|
||||||
|
Loading…
Reference in New Issue
Block a user