Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

reduce can be terminated via (reduced x), first cut at reduce lib

  • Loading branch information...
commit 96e8596cfdd29a2bb245d958683ee5fc1353b87a 1 parent edae983
Rich Hickey authored
16  src/clj/clojure/core.clj
@@ -6001,6 +6001,21 @@
6001 6001
           (let [[shift mask imap switch-type skip-check] (prep-hashes ge default tests thens)]
6002 6002
             `(let [~ge ~e] (case* ~ge ~shift ~mask ~default ~imap ~switch-type :hash-identity ~skip-check))))))))
6003 6003
 
  6004
+
  6005
+;; redefine reduce with internal-reduce
  6006
+(defn reduced
  6007
+  "Wraps x in a way such that a reduce will terminate with the value x"
  6008
+  {:added "1.5"}
  6009
+  [x]
  6010
+  (clojure.lang.Reduced. x))
  6011
+
  6012
+(defn reduced?
  6013
+  "Returns true if x is the result of a call to reduced"
  6014
+  {:inline (fn [x] `(clojure.lang.RT/isReduced ~x ))
  6015
+   :inline-arities #{1}
  6016
+   :added "1.5"}
  6017
+  ([x] (clojure.lang.RT/isReduced x)))
  6018
+
6004 6019
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helper files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6005 6020
 (alter-meta! (find-ns 'clojure.core) assoc :doc "Fundamental library of the Clojure language")
6006 6021
 (load "core_proxy")
@@ -6012,7 +6027,6 @@
6012 6027
 (load "instant")
6013 6028
 (load "uuid")
6014 6029
 
6015  
-;; redefine reduce with internal-reduce
6016 6030
 (defn reduce
6017 6031
   "f should be a function of 2 arguments. If val is not supplied,
6018 6032
   returns the result of applying f to the first 2 items in coll, then
39  src/clj/clojure/core/protocols.clj
@@ -66,14 +66,20 @@
66 66
         (if (.hasNext iter)
67 67
           (loop [ret (.next iter)]
68 68
             (if (.hasNext iter)
69  
-              (recur (f ret (.next iter)))
  69
+              (let [ret (f ret (.next iter))]
  70
+                (if (reduced? ret)
  71
+                  @ret
  72
+                  (recur ret)))
70 73
               ret))
71 74
           (f))))
72 75
    ([coll f val]
73 76
       (let [iter (.iterator coll)]
74 77
         (loop [ret val]
75 78
           (if (.hasNext iter)
76  
-            (recur (f ret (.next iter)))
  79
+            (let [ret (f ret (.next iter))]
  80
+                (if (reduced? ret)
  81
+                  @ret
  82
+                  (recur ret)))
77 83
             ret)))))
78 84
   )
79 85
 
@@ -89,9 +95,12 @@
89 95
    [s f val]
90 96
    (if-let [s (seq s)]
91 97
      (if (chunked-seq? s)
92  
-       (recur (chunk-next s)
93  
-              f
94  
-              (.reduce (chunk-first s) f val))
  98
+       (let [ret (.reduce (chunk-first s) f val)]
  99
+         (if (reduced? ret)
  100
+           @ret
  101
+           (recur (chunk-next s)
  102
+                  f
  103
+                  ret)))
95 104
        (internal-reduce s f val))
96 105
      val))
97 106
  
@@ -102,7 +111,10 @@
102 111
      (loop [i (.i str-seq)
103 112
             val val]
104 113
        (if (< i (.length s))
105  
-         (recur (inc i) (f val (.charAt s i)))
  114
+         (let [ret (f val (.charAt s i))]
  115
+                (if (reduced? ret)
  116
+                  @ret
  117
+                  (recur (inc i) ret)))
106 118
          val))))
107 119
   
108 120
   clojure.lang.ArraySeq
@@ -112,7 +124,10 @@
112 124
          (loop [i (.index a-seq)
113 125
                 val val]
114 126
            (if (< i (alength arr))
115  
-             (recur (inc i) (f val (aget arr i)))
  127
+             (let [ret (f val (aget arr i))]
  128
+                (if (reduced? ret)
  129
+                  @ret
  130
+                  (recur (inc i) ret)))
116 131
              val))))
117 132
   
118 133
   java.lang.Object
@@ -125,7 +140,10 @@
125 140
      (if-let [s (seq s)]
126 141
        ;; roll over to faster implementation if underlying seq changes type
127 142
        (if (identical? (class s) cls)
128  
-         (recur cls (next s) f (f val (first s)))
  143
+         (let [ret (f val (first s))]
  144
+                (if (reduced? ret)
  145
+                  @ret
  146
+                  (recur cls (next s) f ret)))
129 147
          (internal-reduce s f val))
130 148
        val))))
131 149
 
@@ -136,7 +154,10 @@
136 154
          (loop [i (.index a-seq)
137 155
                 val val]
138 156
            (if (< i (alength arr))
139  
-             (recur (inc i) (f val (aget arr i)))
  157
+             (let [ret (f val (aget arr i))]
  158
+                (if (reduced? ret)
  159
+                  @ret
  160
+                  (recur (inc i) ret)))
140 161
              val)))))
141 162
 
142 163
 (defn- emit-array-impls*
6  src/jvm/clojure/lang/ArrayChunk.java
@@ -56,8 +56,14 @@ public IChunk dropFirst(){
56 56
 
57 57
 public Object reduce(IFn f, Object start) {
58 58
 		Object ret = f.invoke(start, array[off]);
  59
+		if(RT.isReduced(ret))
  60
+			return ret;
59 61
 		for(int x = off + 1; x < end; x++)
  62
+			{
60 63
 			ret = f.invoke(ret, array[x]);
  64
+			if(RT.isReduced(ret))
  65
+				return ret;
  66
+			}
61 67
 		return ret;
62 68
 }
63 69
 }
2  src/jvm/clojure/lang/PersistentArrayMap.java
@@ -282,6 +282,8 @@ public void remove(){
282 282
 public Object kvreduce(IFn f, Object init){
283 283
     for(int i=0;i < array.length;i+=2){
284 284
         init = f.invoke(init, array[i], array[i+1]);
  285
+	    if(RT.isReduced(init))
  286
+		    return ((IDeref)init).deref();
285 287
         }
286 288
     return init;
287 289
 }
16  src/jvm/clojure/lang/PersistentHashMap.java
@@ -180,7 +180,9 @@ public Iterator iterator(){
180 180
 
181 181
 public Object kvreduce(IFn f, Object init){
182 182
     init = hasNull?f.invoke(init,null,nullValue):init;
183  
-    if(root != null){
  183
+	if(RT.isReduced(init))
  184
+		return ((IDeref)init).deref();
  185
+	if(root != null){
184 186
         return root.kvreduce(f,init);
185 187
     }
186 188
     return init;
@@ -383,11 +385,13 @@ public ISeq nodeSeq(){
383 385
 	}
384 386
 
385 387
     public Object kvreduce(IFn f, Object init){
386  
-        for(INode node : array)
387  
-            {
388  
-            if(node != null)
  388
+        for(INode node : array){
  389
+            if(node != null){
389 390
                 init = node.kvreduce(f,init);
390  
-            }
  391
+	            if(RT.isReduced(init))
  392
+		            return ((IDeref)init).deref();
  393
+	            }
  394
+	        }
391 395
         return init;
392 396
     }
393 397
 
@@ -1058,6 +1062,8 @@ static public Object kvreduce(Object[] array, IFn f, Object init){
1058 1062
                  if(node != null)
1059 1063
                      init = node.kvreduce(f,init);
1060 1064
                  }
  1065
+             if(RT.isReduced(init))
  1066
+	             return ((IDeref)init).deref();
1061 1067
              }
1062 1068
         return init;
1063 1069
     }
15  src/jvm/clojure/lang/PersistentTreeMap.java
@@ -538,11 +538,20 @@ Node balanceRight(Node parent){
538 538
 
539 539
     public Object kvreduce(IFn f, Object init){
540 540
         init = f.invoke(init, key(), val());
541  
-        if(left() != null)
  541
+	    if(RT.isReduced(init))
  542
+		    return ((IDeref)init).deref();
  543
+
  544
+	    if(left() != null){
542 545
             init = left().kvreduce(f, init);
543  
-        if(right() != null)
  546
+	        if(RT.isReduced(init))
  547
+		        return ((IDeref)init).deref();
  548
+	        }
  549
+	    if(right() != null){
544 550
             init = right().kvreduce(f, init);
545  
-        return init;
  551
+	        if(RT.isReduced(init))
  552
+		        return ((IDeref)init).deref();
  553
+	        }
  554
+	    return init;
546 555
     }
547 556
 
548 557
 
5  src/jvm/clojure/lang/PersistentVector.java
@@ -236,8 +236,11 @@ public Object kvreduce(IFn f, Object init){
236 236
     int step = 0;
237 237
     for(int i=0;i<cnt;i+=step){
238 238
         Object[] array = arrayFor(i);
239  
-        for(int j =0;j<array.length;++j)
  239
+        for(int j =0;j<array.length;++j){
240 240
             init = f.invoke(init,j+i,array[j]);
  241
+            if(RT.isReduced(init))
  242
+	            return ((IDeref)init).deref();
  243
+            }
241 244
         step = array.length;
242 245
     }
243 246
     return init;
4  src/jvm/clojure/lang/RT.java
@@ -1680,6 +1680,10 @@ static public boolean isLineNumberingReader(Reader r){
1680 1680
 	return r instanceof LineNumberingPushbackReader;
1681 1681
 }
1682 1682
 
  1683
+static public boolean isReduced(Object r){
  1684
+	return r instanceof Reduced;
  1685
+}
  1686
+
1683 1687
 static public String resolveClassNameInContext(String className){
1684 1688
 	//todo - look up in context var
1685 1689
 	return className;
18  src/jvm/clojure/lang/Reduced.java
... ...
@@ -0,0 +1,18 @@
  1
+// Copyright (c) Metadata Partners, LLC.
  2
+// All rights reserved.
  3
+
  4
+/* rich 4/30/12 */
  5
+
  6
+package clojure.lang;
  7
+
  8
+public class Reduced implements IDeref{
  9
+Object val;
  10
+
  11
+public Reduced(Object val){
  12
+	this.val = val;
  13
+}
  14
+
  15
+public Object deref(){
  16
+	return val;
  17
+}
  18
+}

0 notes on commit 96e8596

Please sign in to comment.
Something went wrong with that request. Please try again.