# CLJS error in sorting vectors

**URL:** https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799
**Category:** Troubleshooting
**Tags:** clojurescript
**Created:** [April 15, 2020, 10:43pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799 "2020-04-15T22:43:38Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Webdev\_Tory](https://clojureverse.org/user_avatar/clojureverse.org/webdev_tory/32/3781_2.png) [@Webdev\_Tory](https://clojureverse.org/u/Webdev_Tory)
#### Post date: [April 15, 2020, 10:43pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/1 "2020-04-15T22:43:38Z")

</div>

After spending an aggravatingly long time trying to do a 2-step sort maps in cljs, as per [this example](https://clojuredocs.org/clojure.core/sort-by) with `juxt`, I reduced my errors to the following minimal example. It appears to be a fairly fundamental bug in Clojurescript, but I’m not sure where to report it. Another set of eyes would be nice to make sure I’m not hallucinating after fighting this all afternoon.

```clojure
(sort [1 22 3])
;; => (1 3 22) ;; CORRECT

(sort [[0 1] [0 22] [0 3]])
;; => ([0 1] [0 3] [0 22]) ;; STILL CORRECT

 (sort < [[0 1] [0 22] [0 3]])
  ;; => ([0 1] [0 22] [0 3]) ;; STRING-ORDER (WRONG)

```

---

<div class="post-metadata">

### Author: ![andy.fingerhut](https://clojureverse.org/user_avatar/clojureverse.org/andy.fingerhut/32/1244_2.png) [@andy.fingerhut](https://clojureverse.org/u/andy.fingerhut)
#### Post date: [April 15, 2020, 11:46pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/2 "2020-04-15T23:46:55Z")

</div>

> [@Webdev\_Tory](#):
>
> (sort \< [[0 1] [0 22] [0 3]])

I do not know the origin or background here, but if you try this at a ClojureScript REPL, you will see a warning if you try to compare two vectors using `<`, but not if you call `sort` using `<` with vectors. I do not know why, but suspect that the warning is probably a kind of static analysis kind of thing done by the ClojureScript compiler, and it does not detect it when `<` is called as a higher-order function, as it is when called from `sort`:

```auto
$ clojure -Sdeps "{:deps {org.clojure/clojurescript {:mvn/version \"1.10.597\"}}}" -m cljs.main --repl-env node
ClojureScript 1.10.597
cljs.user=> (< [0 1] [0 2])
WARNING: cljs.core/<, all arguments must be numbers, got [cljs.core/IVector cljs.core/IVector] instead at line 1 <cljs repl>
true
cljs.user=> (sort < [[0 1] [0 22] [0 3]])
([0 1] [0 22] [0 3])

```

---

<div class="post-metadata">

### Author: ![andy.fingerhut](https://clojureverse.org/user_avatar/clojureverse.org/andy.fingerhut/32/1244_2.png) [@andy.fingerhut](https://clojureverse.org/u/andy.fingerhut)
#### Post date: [April 15, 2020, 11:48pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/3 "2020-04-15T23:48:29Z")

</div>

It seems that the correct thing to do is not to use `<` in this case, just use `sort` without an explicit comparison function, or if you want to supply an explicit one for some reason, use `compare` instead of `<`.

---

<div class="post-metadata">

### Author: ![dave.liepmann](https://clojureverse.org/user_avatar/clojureverse.org/dave.liepmann/32/5211_2.png) [@dave.liepmann](https://clojureverse.org/u/dave.liepmann)
#### Post date: [April 16, 2020, 7:29am UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/4 "2020-04-16T07:29:33Z")

</div>

I’m moderately confident that you want to read [this thread](https://v2.clojureverse.org/t/tuple-ordering/4911). It’s not clear what your particular use case is but if `(sort-by (juxt first second #(nth % 2)) [...])` isn’t sufficient for your purposes [1] then that thread has some more general comparators that might be what you’re looking for. But it also contains an explanation of what’s going on under the hood (albeit in Clojure, not CLJS). Basically, `sort` by itself will rely on `compare`, which orders vectors like this:

> - vectors are sorted from fewest elements to most elements, with [lexicographic ordering](http://en.wikipedia.org/wiki/Lexicographical_order) among equal length vectors.

Supplying `<` as a non-default comparator will break this behavior as it tries to interpret the vectors as numbers, which as Andy points out will give you a warning in the CLJS REPL. It may be worthwhile to note that in JVM Clojure it throws `java.lang.ClassCastException` because `class clojure.lang.PersistentVector cannot be cast to class java.lang.Number`. Simply put, less-than expects numbers.

[1]: It’s unclear from your clojuredocs/sort-by link what you wanted to do with `juxt`

---

<div class="post-metadata">

### Author: ![Webdev\_Tory](https://clojureverse.org/user_avatar/clojureverse.org/webdev_tory/32/3781_2.png) [@Webdev\_Tory](https://clojureverse.org/u/Webdev_Tory)
#### Post date: [April 16, 2020, 10:11pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/5 "2020-04-16T22:11:06Z")

</div>

My original goal was to get a two-level sort: sort by value and, when that’s equal, sort by alpha of key. But in general, the ability to do layered sorts.

---

<div class="post-metadata">

### Author: ![Webdev\_Tory](https://clojureverse.org/user_avatar/clojureverse.org/webdev_tory/32/3781_2.png) [@Webdev\_Tory](https://clojureverse.org/u/Webdev_Tory)
#### Post date: [April 17, 2020, 3:22pm UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/6 "2020-04-17T15:22:40Z")

</div>

Perfectly helpful. Thanks! That link is exactly appropo. Including usages of juxt to get secondary orderings. My personal mistake seems to have been thinking that `(sort < coll)` or `>` were, in fact, what sort[-by] does automatically with no function specified. Apparently not!

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [October 17, 2020, 3:22am UTC](https://clojureverse.org/t/cljs-error-in-sorting-vectors/5799/7 "2020-10-17T03:22:51Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
