hy/hy/contrib/sequences.hy

63 lines
2.5 KiB
Hy
Raw Permalink Normal View History

2019-02-07 14:57:35 +01:00
;; Copyright 2019 the authors.
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
2016-11-08 05:28:12 +01:00
(defclass Sequence []
[--init-- (fn [self func]
"initialize a new sequence with a function to compute values"
(setv (. self func) func)
(setv (. self cache) [])
2016-11-30 22:45:21 +01:00
(setv (. self high-water) -1))
2016-11-08 05:28:12 +01:00
--getitem-- (fn [self n]
"get nth item of sequence"
(if (hasattr n "start")
(gfor x (range n.start n.stop (or n.step 1))
(get self x))
2016-11-08 05:28:12 +01:00
(do (when (neg? n)
2016-12-08 01:32:37 +01:00
; Call (len) to force the whole
; sequence to be evaluated.
2016-11-08 05:28:12 +01:00
(len self))
(if (<= n (. self high-water))
(get (. self cache) n)
(do (while (< (. self high-water) n)
(setv (. self high-water) (inc (. self high-water)))
(.append (. self cache) (.func self (. self high-water))))
(get self n))))))
--iter-- (fn [self]
"create iterator for this sequence"
(setv index 0)
2016-11-30 22:45:21 +01:00
(try (while True
2016-11-08 05:28:12 +01:00
(yield (get self index))
(setv index (inc index)))
(except [IndexError]
(return))))
2016-11-08 05:28:12 +01:00
--len-- (fn [self]
"length of the sequence, dangerous for infinite sequences"
(setv index (. self high-water))
2016-12-08 01:04:59 +01:00
(try (while True
2016-11-08 05:28:12 +01:00
(get self index)
(setv index (inc index)))
(except [IndexError]
2016-11-08 05:28:12 +01:00
(len (. self cache)))))
2016-12-08 01:32:37 +01:00
max-items-in-repr 10
2016-11-08 05:28:12 +01:00
--str-- (fn [self]
"string representation of this sequence"
2016-12-08 01:32:37 +01:00
(setv items (list (take (inc self.max-items-in-repr) self)))
(.format (if (> (len items) self.max-items-in-repr)
2016-11-08 05:28:12 +01:00
"[{0}, ...]"
"[{0}]")
(.join ", " (map str items))))
--repr-- (fn [self]
"string representation of this sequence"
(.--str-- self))])
(defmacro seq [param &rest seq-code]
`(Sequence (fn ~param (do ~@seq-code))))
2016-12-08 01:04:59 +01:00
(defmacro defseq [seq-name param &rest seq-code]
2018-01-05 21:51:00 +01:00
`(setv ~seq-name (Sequence (fn ~param (do ~@seq-code)))))
2016-11-08 05:28:12 +01:00
(defn end-sequence []
"raise IndexError exception to signal end of sequence"
(raise (IndexError "list index out of range")))