summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-04-20 17:41:15 +0000
committerRich Hickey <richhickey@gmail.com>2008-04-20 17:41:15 +0000
commit37713c695d53f08de17b3daec013e7c396769ca9 (patch)
treeb63901cd5b1b781da106ba53467211e3218e547f /src
parent9e24fabf1232f129e5aac45802cce6dfd5e300ce (diff)
made lazy-cons lazy for both first and rest
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj10
-rw-r--r--src/jvm/clojure/lang/LazySeq.java77
2 files changed, 82 insertions, 5 deletions
diff --git a/src/boot.clj b/src/boot.clj
index bee1bc0f..9478262c 100644
--- a/src/boot.clj
+++ b/src/boot.clj
@@ -385,13 +385,13 @@
(defmacro lazy-cons
"Expands to code which produces a seq object whose first is
- first-expr (evaluated) and whose rest is rest-expr, which is not
- evaluated until rest is called. rest-expr will be evaluated at most
- once per step in the sequence, e.g. calling rest repeatedly on the
- head of the seq evaluates rest-expr once - the value it yields is
+ first-expr and whose rest is rest-expr, neither of which is
+ evaluated until first/rest is called. Each expr will be evaluated at most
+ once per step in the sequence, e.g. calling first/rest repeatedly on the
+ same node of the seq evaluates first/rest-expr once - the values they yield are
cached."
[first-expr & rest-expr]
- (list 'fnseq first-expr (list* `fn [] rest-expr)))
+ (list 'new 'clojure.lang.LazySeq (list `fn [] first-expr) (list* `fn [] rest-expr)))
diff --git a/src/jvm/clojure/lang/LazySeq.java b/src/jvm/clojure/lang/LazySeq.java
new file mode 100644
index 00000000..8ebcaf68
--- /dev/null
+++ b/src/jvm/clojure/lang/LazySeq.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Apr 20, 2008 */
+
+package clojure.lang;
+
+public class LazySeq extends ASeq{
+
+IFn _firstFn;
+Object _first;
+IFn _restFn;
+ISeq _rest;
+
+public LazySeq(IFn firstFn, IFn restFn){
+ this._firstFn = firstFn;
+ this._restFn = restFn;
+ this._first = null;
+ this._rest = null;
+}
+
+LazySeq(IPersistentMap meta, Object first, ISeq rest){
+ super(meta);
+ this._first = first;
+ this._rest = rest;
+}
+
+synchronized public Object first(){
+ if(_firstFn != null)
+ {
+ try
+ {
+ _first = _firstFn.invoke();
+ }
+ catch(Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ _firstFn = null;
+ }
+ return _first;
+}
+
+synchronized public ISeq rest(){
+ //force sequential evaluation
+ first();
+ if(_restFn != null)
+ {
+ try
+ {
+ _rest = (ISeq) _restFn.invoke();
+ }
+ catch(Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ _restFn = null;
+ }
+ return _rest;
+}
+
+synchronized public LazySeq withMeta(IPersistentMap meta){
+ if(meta == meta())
+ return this;
+ //force before copying
+ rest();
+ return new LazySeq(meta, _first, _rest);
+}
+
+}