70 lines
2.1 KiB
Hy
70 lines
2.1 KiB
Hy
;; Copyright 2020 the authors.
|
|
;; This file is part of Hy, which is free software licensed under the Expat
|
|
;; license. See the LICENSE.
|
|
|
|
(defclass Sequence []
|
|
|
|
(defn --init-- [self func]
|
|
"initialize a new sequence with a function to compute values"
|
|
(setv (. self func) func)
|
|
(setv (. self cache) [])
|
|
(setv (. self high-water) -1))
|
|
|
|
(defn --getitem-- [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))
|
|
(do (when (neg? n)
|
|
; Call (len) to force the whole
|
|
; sequence to be evaluated.
|
|
(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))))))
|
|
|
|
(defn --iter-- [self]
|
|
"create iterator for this sequence"
|
|
(setv index 0)
|
|
(try (while True
|
|
(yield (get self index))
|
|
(setv index (inc index)))
|
|
(except [IndexError]
|
|
(return))))
|
|
|
|
(defn --len-- [self]
|
|
"length of the sequence, dangerous for infinite sequences"
|
|
(setv index (. self high-water))
|
|
(try (while True
|
|
(get self index)
|
|
(setv index (inc index)))
|
|
(except [IndexError]
|
|
(len (. self cache)))))
|
|
|
|
(setv max-items-in-repr 10)
|
|
|
|
(defn --str-- [self]
|
|
"string representation of this sequence"
|
|
(setv items (list (take (inc self.max-items-in-repr) self)))
|
|
(.format (if (> (len items) self.max-items-in-repr)
|
|
"[{0}, ...]"
|
|
"[{0}]")
|
|
(.join ", " (map str items))))
|
|
|
|
(defn --repr-- [self]
|
|
"string representation of this sequence"
|
|
(.--str-- self)))
|
|
|
|
(defmacro seq [param &rest seq-code]
|
|
`(Sequence (fn ~param (do ~@seq-code))))
|
|
|
|
(defmacro defseq [seq-name param &rest seq-code]
|
|
`(setv ~seq-name (Sequence (fn ~param (do ~@seq-code)))))
|
|
|
|
(defn end-sequence []
|
|
"raise IndexError exception to signal end of sequence"
|
|
(raise (IndexError "list index out of range")))
|