Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in ClojureScript by

This is due to {{cljs.repl}}'s read-then-print processing of string representations of return values that come back from the JS env. As of release 2371, the relevant code fragment lives here:

https://github.com/clojure/clojurescript/blob/r2371/src/clj/cljs/repl.clj#L156

A larger snippet to demonstrate this:

ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14) {1 2, 3 4, 5 6, 7 8, 9 10, 11 12, 13 14} ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) {7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6} ClojureScript:cljs.user> (seq (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)) ([1 2] [3 4] [5 6] [7 8] [9 10] [11 12] [13 14] [15 16] [17 18]) ClojureScript:cljs.user> (hash-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) {7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}

This issue seems to be the most likely cause of the problem described in (link: http://stackoverflow.com/questions/26349324/clojurescript-array-map-order text: this StackOverflow question). It would be nice to print ordered collections in the "expected" way to prevent user confusion.

7 Answers

0 votes
by

Comment made by: dnolen

How is this handled in Clojure?

0 votes
by

Comment made by: michalmarczyk

The built-in REPL simply prints string representations of values to * } without attempting to read them back in first.

0 votes
by

Comment made by: dnolen

Well the result of REPL evaluation is a string unlike Clojure, in order to get a proper print at the ClojureScript REPL it seems necessary to read back the result. I will say it's not clear to me {{array-map}} promises anything about order anyway.

0 votes
by
_Comment made by: michalmarczyk_

It does – see http://clojure.org/data_structures, where it says


ArrayMaps
When doing code form manipulation it is often desirable to have a map which maintains key order. An array map is such a map - it is simply implemented as an array of key val key val... As such, it has linear lookup performance, and is only suitable for very small maps. It implements the full map interface. New ArrayMaps can be created with the array-map function. Note that an array map will only maintain sort order when un-'modified'. Subsequent assoc-ing will eventually cause it to 'become' a hash-map.


This snippet has been there for as long as I can remember; and this particular feature comes up in various online discussions from time to time. The docstrings for {{array-map}} (the core function) are unambiguous in their promise to construct array maps in both Clojure and ClojureScript.

As for the issue at hand, I do think it's a very minor one (hence the "Trivial" priority), but it is real – the representation printed at the REPL is out of line with the string returned from {{pr-str}} on the same value. In fact, one way to fix this would be to use {{pr-str}} representations computed on the CLJS side. (There may be some complications here, though, which we'd have to work out.)
0 votes
by

Comment made by: dnolen

Thanks for pointing out the API promise. OK, yeah I don't really have a good idea for how do this but a patch that isn't too ugly is welcome :)

0 votes
by

Comment made by: mfikes

I think this is no longer reproducible. For example {{(apply array-map (range 100))}} prints in an ordered way. There is also no longer a {{read-string}} call in {{repl.cljc}}.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJS-872 (reported by michalmarczyk)
...