Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Commit 0924a06

Browse files
Merge branch 'primary-master' (1.7) into android
2 parents 4ab16e2 + a752736 commit 0924a06

File tree

9 files changed

+125
-44
lines changed

9 files changed

+125
-44
lines changed

changes.md

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,50 @@
22

33
# Changes to Clojure in Version 1.7
44

5-
## 1 New and Improved Features
5+
## 1 Compatibility Notes
66

7-
### 1.1 Transducers
7+
Please be aware of the following issues when upgrading to Clojure 1.7.
8+
9+
### Seqs on Java iterators that return the same mutating object
10+
11+
Seqs are fundamentally incompatible with Java iterators that return
12+
the same mutating object on every call to next(). Some Clojure
13+
libraries incorrectly rely on calling seq on such iterators.
14+
15+
In 1.7, iterator-seqs are chunked, which will cause many of these
16+
incorrect usages to return incorrect results immediately.
17+
18+
The `seq` and `iterator-seq` docstrings have been updated to include
19+
an explicit warning. Libraries that incorrectly use `seq` and
20+
`iterator-seq` will need to be fixed before running against 1.7.
21+
22+
* [CLJ-1669](http://dev.clojure.org/jira/browse/CLJ-1669)
23+
* [CLJ-1738](http://dev.clojure.org/jira/browse/CLJ-1738)
24+
25+
### Thread owner check removed on transients
26+
27+
Prior to Clojure 1.7, transients would allow modification only from the
28+
thread that created the transient. This check has been removed. It is
29+
still a requirement that transients should be updated by only a single
30+
thread at a time.
31+
32+
This constraint was relaxed to allow transients to be used in cases where
33+
code is multiplexed across multiple threads in a pool (such as go blocks
34+
in core.async).
35+
36+
### keys/vals require custom map type to implement Iterable
37+
38+
Invoking `keys` or `vals` on a custom map type that implements IPersistentMap
39+
will now use the Iterable iterator() method instead of accessing entries
40+
via the seq of the map. There have been no changes in the type hierarchy
41+
(IPersistentMap has always extended Iterable) but former map-like instances
42+
may have skipped implementing this method in the past.
43+
44+
* [CLJ-1602](http://dev.clojure.org/jira/browse/CLJ-1602)
45+
46+
## 2 New and Improved Features
47+
48+
### 2.1 Transducers
849

950
Transducers is a new way to decouple algorithmic transformations from their
1051
application in different contexts. Transducers are functions that transform
@@ -16,7 +57,6 @@ Many existing sequence functions now have a new arity (one fewer argument
1657
than before). This arity will return a transducer that represents the same
1758
logic but is independent of lazy sequence processing. Functions included are:
1859

19-
* conj (conjs to [])
2060
* map
2161
* mapcat
2262
* filter
@@ -38,7 +78,7 @@ logic but is independent of lazy sequence processing. Functions included are:
3878
Additionally some new transducer functions have been added:
3979

4080
* cat - concatenates the contents of each input
41-
* de-dupe - removes consecutive duplicated values
81+
* dedupe - removes consecutive duplicated values
4282
* random-sample - returns items from coll with random probability
4383

4484
And this function can be used to make completing transforms:
@@ -51,12 +91,12 @@ transducers in different ways:
5191
* sequence - takes a transformation and a coll and produces a lazy seq
5292
* transduce - reduce with a transformation (eager)
5393
* eduction - returns a reducible/iterable of applications of the transducer to items in coll. Applications are re-performed with every reduce/iterator.
54-
* run! - run the transformation for side effects on the collection
5594

5695
There have been a number of internal changes to support transducers:
5796

5897
* volatiles - there are a new set of functions (volatile!, vswap!, vreset!, volatile?) to create and use volatile "boxes" to hold state in stateful transducers. Volatiles are faster than atoms but give up atomicity guarantees so should only be used with thread isolation.
5998
* array iterators - added support for iterators over arrays
99+
* conj can be used as a reducing function and will conj to []
60100

61101
Some related issues addressed during development:
62102
* [CLJ-1511](http://dev.clojure.org/jira/browse/CLJ-1511)
@@ -73,7 +113,7 @@ Some related issues addressed during development:
73113
* [CLJ-1669](http://dev.clojure.org/jira/browse/CLJ-1669)
74114
* [CLJ-1723](http://dev.clojure.org/jira/browse/CLJ-1723)
75115

76-
### 1.2 Reader Conditionals
116+
### 2.2 Reader Conditionals
77117

78118
Reader Conditionals are a new capability to support portable code that
79119
can run on multiple Clojure platforms with only small changes. In
@@ -88,13 +128,14 @@ prior to .cljc.
88128
A new reader form can be used to specify "reader conditional" code in
89129
cljc files (and *only* cljc files). Each platform defines a feature
90130
identifying the platform (:clj, :cljs, :cljr). The reader conditional
91-
specifies code that is read conditionally based on the feature/
131+
specifies code that is read conditionally based on the feature. The
132+
REPL also allows reader conditionals.
92133

93134
Form #? takes a list of alternating feature and expression. These are
94135
checked like cond and the selected expression is read and returned. Other
95-
branches are unread. If no branch is selected, the reader reads nothing
96-
(not nil, but literally as if reading ""). An optional ":default" branch
97-
can be used as a fallthrough.
136+
branches are read but skipped. If no branch is selected, the reader reads
137+
nothing (not nil, but literally as if reading no form). An optional
138+
`:default` branch can be used as a fallthrough.
98139

99140
Reader conditional with 2 features and a default:
100141

@@ -104,14 +145,14 @@ Reader conditional with 2 features and a default:
104145

105146
There is also a reader conditional splicing form. The evaluated expression
106147
should be sequential and will be spliced into the surrounded code, similar
107-
to unqoute-splicing.
148+
to unquote-splicing.
108149

109150
For example:
110151

111152
[1 2 #?@(:clj [3 4] :cljs [5 6])]
112153

113154
This form would read as [1 2 3 4] on Clojure, [1 2 5 6] on ClojureScript,
114-
and [1 2] on any other platform.
155+
and [1 2] on any other platform. Splicing is not allowed at the top level.
115156

116157
Additionally, the reader can now be invoked with options for the features
117158
to use and how to interpret reader conditionals. By default, reader conditionals
@@ -130,8 +171,9 @@ http://dev.clojure.org/display/design/Reader+Conditionals
130171
* [CLJ-1699](http://dev.clojure.org/jira/browse/CLJ-1699)
131172
* [CLJ-1700](http://dev.clojure.org/jira/browse/CLJ-1700)
132173
* [CLJ-1728](http://dev.clojure.org/jira/browse/CLJ-1728)
174+
* [CLJ-1706](http://dev.clojure.org/jira/browse/CLJ-1706)
133175

134-
### 1.3 Keyword and Symbol Construction
176+
### 2.3 Keyword and Symbol Construction
135177

136178
In response to issues raised in [CLJ-1439](http://dev.clojure.org/jira/browse/CLJ-1439),
137179
several changes have been made in symbol and keyword construction:
@@ -143,7 +185,7 @@ in a performance increase.
143185
2) Keywords are cached and keyword construction includes a cache check. A change was made
144186
to only clear the cache reference queue when there is a cache miss.
145187

146-
### 1.4 Warn on Boxed Math
188+
### 2.4 Warn on Boxed Math
147189

148190
One source of performance issues is the (unintended) use of arithmetic operations on
149191
boxed numbers. To make detecting the presence of boxed math easier, a warning will now
@@ -167,7 +209,7 @@ Example use:
167209
* [CLJ-1535](http://dev.clojure.org/jira/browse/CLJ-1535)
168210
* [CLJ-1642](http://dev.clojure.org/jira/browse/CLJ-1642)
169211

170-
### 1.5 update - like update-in for first level
212+
### 2.5 update - like update-in for first level
171213

172214
`update` is a new function that is like update-in specifically for first-level keys:
173215

@@ -184,7 +226,7 @@ Example use:
184226

185227
* [CLJ-1251](http://dev.clojure.org/jira/browse/CLJ-1251)
186228

187-
### 1.6 Faster reduce and iterator paths
229+
### 2.6 Faster reduce and iterator paths
188230

189231
Several important Clojure functions now return sequences that also
190232
contain fast reduce() (or in some cases iterator()) paths. In many
@@ -221,7 +263,7 @@ eduction.
221263
* [CLJ-1726](http://dev.clojure.org/jira/browse/CLJ-1726)
222264
* [CLJ-1727](http://dev.clojure.org/jira/browse/CLJ-1727)
223265

224-
### 1.7 Printing as data
266+
### 2.7 Printing as data
225267

226268
There have been enhancements in how the REPL prints values without a
227269
print-method, specifically Throwable and the fallthrough Object case.
@@ -256,19 +298,26 @@ map data: `Throwable->map`.
256298

257299
* [CLJ-1703](http://dev.clojure.org/jira/browse/CLJ-1703)
258300
* [CLJ-1716](http://dev.clojure.org/jira/browse/CLJ-1716)
301+
* [CLJ-1735](http://dev.clojure.org/jira/browse/CLJ-1735)
259302

260-
## 2 Enhancements
303+
### 2.8 run!
261304

262-
### 2.1 Error messages
305+
run! is a new function that takes a side effect reducing function and runs
306+
it for all items in a collection via reduce. The accumulator is ignored and
307+
nil is returned.
308+
309+
(run! println (range 10))
310+
311+
## 3 Enhancements
312+
313+
### 3.1 Error messages
263314

264315
* [CLJ-1261](http://dev.clojure.org/jira/browse/CLJ-1261)
265316
Invalid defrecord results in exception attributed to consuming ns instead of defrecord ns
266-
* [CLJ-1169](http://dev.clojure.org/jira/browse/CLJ-1169)
267-
Report line,column, and source in defmacro errors
268317
* [CLJ-1297](http://dev.clojure.org/jira/browse/CLJ-1297)
269318
Give more specific hint if namespace with "-" not found to check file uses "_"
270319

271-
### 2.2 Documentation strings
320+
### 3.2 Documentation strings
272321

273322
* [CLJ-1417](http://dev.clojure.org/jira/browse/CLJ-1417)
274323
clojure.java.io/input-stream has incorrect docstring
@@ -282,8 +331,10 @@ map data: `Throwable->map`.
282331
Fix typo in deftype docstring
283332
* [CLJ-1478](http://dev.clojure.org/jira/browse/CLJ-1378)
284333
Fix typo in clojure.main usage
334+
* [CLJ-1738](http://dev.clojure.org/jira/browse/CLJ-1738)
335+
Clarify usage on Java iterators in seq and iterator-seq
285336

286-
### 2.3 Performance
337+
### 3.3 Performance
287338

288339
* [CLJ-1430](http://dev.clojure.org/jira/browse/CLJ-1430)
289340
Improve performance of partial with more unrolling
@@ -300,7 +351,7 @@ map data: `Throwable->map`.
300351
* [CLJ-1695](http://dev.clojure.org/jira/browse/CLJ-1695)
301352
Fixed reflection call in variadic vector-of constructor
302353

303-
### 2.4 Other enhancements
354+
### 3.4 Other enhancements
304355

305356
* [CLJ-1191](http://dev.clojure.org/jira/browse/CLJ-1191)
306357
Improve apropos to show some indication of namespace of symbols found
@@ -331,7 +382,7 @@ map data: `Throwable->map`.
331382
* [CLJ-1683](http://dev.clojure.org/jira/browse/CLJ-1683)
332383
Change reduce tests to better catch reduce without init bugs
333384

334-
## 3 Bug Fixes
385+
## 4 Bug Fixes
335386

336387
* [CLJ-1362](http://dev.clojure.org/jira/browse/CLJ-1362)
337388
Reduce broken on some primitive vectors
@@ -389,6 +440,8 @@ map data: `Throwable->map`.
389440
Use equals() instead of == when resolving Symbol
390441
* [CLJ-1195](http://dev.clojure.org/jira/browse/CLJ-1195)
391442
emit-hinted-impl expands to ns-qualified invocation of fn
443+
* [CLJ-1237](http://dev.clojure.org/jira/browse/CLJ-1237)
444+
reduce of sequence that switches between chunked and unchunked many times throws StackOverflow
392445

393446
# Changes to Clojure in Version 1.6
394447

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<artifactId>clojure</artifactId>
66
<name>clojure</name>
77
<packaging>jar</packaging>
8-
<version>1.7.0-RC1</version>
8+
<version>1.7.0</version>
99
<url>http://clojure.org/</url>
1010
<description>Clojure core environment and runtime library.</description>
1111

src/clj/clojure/core.clj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@
128128
:doc "Returns a seq on the collection. If the collection is
129129
empty, returns nil. (seq nil) returns nil. seq also works on
130130
Strings, native Java arrays (of reference types) and any objects
131-
that implement Iterable."
131+
that implement Iterable. Note that seqs cache values, thus seq
132+
should not be used on any Iterable whose iterator repeatedly
133+
returns the same mutable object."
132134
:tag clojure.lang.ISeq
133135
:added "1.0"
134136
:static true}
@@ -5479,7 +5481,9 @@
54795481

54805482
(defn iterator-seq
54815483
"Returns a seq on a java.util.Iterator. Note that most collections
5482-
providing iterators implement Iterable and thus support seq directly."
5484+
providing iterators implement Iterable and thus support seq directly.
5485+
Seqs cache values, thus iterator-seq should not be used on any
5486+
iterator that repeatedly returns the same mutable object."
54835487
{:added "1.0"
54845488
:static true}
54855489
[iter]

src/clj/clojure/core/protocols.clj

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@
5252
(recur ret)))
5353
ret)))))
5454

55+
(defn- naive-seq-reduce
56+
"Reduces a seq, ignoring any opportunities to switch to a more
57+
specialized implementation."
58+
[s f val]
59+
(loop [s (seq s)
60+
val val]
61+
(if s
62+
(let [ret (f val (first s))]
63+
(if (reduced? ret)
64+
@ret
65+
(recur (next s) ret)))
66+
val)))
67+
68+
(defn- interface-or-naive-reduce
69+
"Reduces via IReduceInit if possible, else naively."
70+
[coll f val]
71+
(if (instance? clojure.lang.IReduceInit coll)
72+
(.reduce ^clojure.lang.IReduceInit coll f val)
73+
(naive-seq-reduce coll f val)))
74+
5575
(extend-protocol CollReduce
5676
nil
5777
(coll-reduce
@@ -119,7 +139,7 @@
119139
(recur (chunk-next s)
120140
f
121141
ret)))
122-
(coll-reduce s f val))
142+
(interface-or-naive-reduce s f val))
123143
val))
124144

125145
clojure.lang.StringSeq
@@ -143,13 +163,12 @@
143163
f f
144164
val val]
145165
(if-let [s (seq s)]
146-
;; roll over to faster implementation if underlying seq changes type
147166
(if (identical? (class s) cls)
148167
(let [ret (f val (first s))]
149168
(if (reduced? ret)
150169
@ret
151170
(recur cls (next s) f ret)))
152-
(coll-reduce s f val))
171+
(interface-or-naive-reduce s f val))
153172
val))))
154173

155174
(defprotocol IKVReduce

src/clj/clojure/core_print.clj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,10 @@
413413
(defmethod print-method StackTraceElement [^StackTraceElement o ^Writer w]
414414
(print-method [(symbol (.getClassName o)) (symbol (.getMethodName o)) (.getFileName o) (.getLineNumber o)] w))
415415

416-
(defn Throwable->map [^Throwable o]
416+
(defn Throwable->map
417+
"Constructs a data representation for a Throwable."
418+
{:added "1.7"}
419+
[^Throwable o]
417420
(let [base (fn [^Throwable t]
418421
(let [m {:type (class t)
419422
:message (.getLocalizedMessage t)

src/jvm/clojure/lang/Compiler.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6635,16 +6635,6 @@ public static Object macroexpand1(Object x) {
66356635
// hide the 2 extra params for a macro
66366636
throw new ArityException(e.actual - 2, e.name);
66376637
}
6638-
catch(Throwable e)
6639-
{
6640-
if(!(e instanceof CompilerException)) {
6641-
Integer line = (Integer) LINE.deref();
6642-
Integer column = (Integer) COLUMN.deref();
6643-
String source = (String) SOURCE.deref();
6644-
throw new CompilerException(source, line, column, e);
6645-
} else
6646-
throw (CompilerException) e;
6647-
}
66486638
}
66496639
else
66506640
{

test/clojure/test_clojure/control.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@
373373
:a (char 97)))
374374
(testing "test error on duplicate test constants"
375375
(is (thrown-with-msg?
376-
clojure.lang.Compiler$CompilerException
376+
IllegalArgumentException
377377
#"Duplicate case test constant: 1"
378378
(eval `(case 0 1 :x 1 :y)))))
379379
(testing "test correct behaviour on Number truncation"

test/clojure/test_clojure/errors.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
["let .* in %s:\\d+" '(let [a])]
4949
["let .* in %s:\\d+" '(let (a))]
5050
["renamed-with-open .* in %s:\\d+" '(renamed-with-open [a])]]]
51-
(is (thrown-with-msg? clojure.lang.Compiler$CompilerException
51+
(is (thrown-with-msg? IllegalArgumentException
5252
(re-pattern (format msg-regex-str *ns*))
5353
(macroexpand form)))))
5454

test/clojure/test_clojure/sequences.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@
9090
(reduce f start (range 5))))]
9191
(is (= [0 1 2 3 4] (into [] iri)))))
9292

93+
;; CLJ-1237 regression test
94+
(deftest reduce-with-varying-impls
95+
(is (= 1000000
96+
(->> (repeat 500000 (cons 1 [1]))
97+
(apply concat)
98+
(reduce +))))
99+
100+
(is (= 4500000
101+
(->> (range 100000)
102+
(mapcat (fn [_] (java.util.ArrayList. (range 10))))
103+
(reduce +)))))
104+
93105
(deftest test-equality
94106
; lazy sequences
95107
(are [x y] (= x y)

0 commit comments

Comments
 (0)