1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-05 08:16:16 +00:00
janet/examples/lazyseqs.dst

107 lines
2.2 KiB
Plaintext
Raw Normal View History

# An example implementation of functional, lazy
# sequences, like in clojure.
# Use with (import "./path/to/this/file" :prefix "seq/")
(defn- mem0 [f]
"Memoize a 0 arity function."
(var state nil)
(var loaded nil)
(fn []
(if loaded
state
(do
(def n (f))
2018-03-16 22:15:34 +00:00
(:= state n)
(:= loaded true)
n))))
2018-03-16 22:15:34 +00:00
# This creates one more closure than necessary but oh well
(defmacro delay
"Macro for lazy evaluation"
[& forms] (tuple mem0 (apply1 tuple (array-concat ['fn []] forms))))
# Use tuples instead of structs to save memory
(def HEAD :private 0)
(def TAIL :private 1)
(defn empty-seq
"The empty sequence."
[] nil)
(defn cons
"Create a new sequence by prepending a value to the original sequence."
[h t]
(delay (tuple h t)))
2018-03-16 17:40:10 +00:00
(defn cons1
"Create a new sequence cons by prepending a value to the original sequence."
[h t]
(tuple h t))
(defn empty?
"Check if a sequence is empty."
[s]
(not (s)))
(defn head
"Get the next value of the sequence."
[s]
(get (s) HEAD))
(defn tail
"Get the rest of a sequence"
[s]
(get (s) TAIL))
2018-03-16 17:40:10 +00:00
(defn range2
"Return a sequence of integers [start, end)."
[start end]
(if (< start end)
(cons start (range2 (+ 1 start) end))
empty-seq))
2018-03-16 17:40:10 +00:00
(defn range
"Return a sequence of integers [0, end)."
[end]
(range2 0 end))
(defn map
"Return a sequence that is the result of apply f to each value in s."
[f s]
2018-03-16 17:40:10 +00:00
(delay
(def x (s))
(if x (tuple (f (get x HEAD)) (map f (get x TAIL))))))
(defn realize
"Force evaluation of a lazy sequence."
[s]
(when (s) (realize (tail s))))
(defn realize-map [f s]
"Evaluate f on each member of the sequence. Forces evaluation."
(when (s) (f (head s)) (realize-map f (tail s))))
(defn drop
"Ignores the first n values of the sequence and returns the rest."
[n s]
2018-03-16 17:40:10 +00:00
(delay
(def x (s))
(if (s) (if (zero? n) s (drop (- n 1) (tail s))) empty-seq)))
(defn take
"Returns at most the first n values of s."
[n s]
(if (and (s) (pos? n))
(cons (head s) (take (- n 1) (tail s)))
empty-seq))
2018-03-16 17:40:10 +00:00
(defn take-while
"Returns a sequence of values until the predicate is false."
[pred s]
(delay
(def x (s))
(when x
(def thehead (get HEAD x))
(if thehead (tuple thehead (take-while pred (get TAIL x)))))))
2018-03-16 17:40:10 +00:00