clj-commons / clj-commons/ordered
Issues with ordered/map data literals
- Dominant language
- Clojure
- Stars
- 267
- Forks
- 40
- Avg merge
- 14h 2m
- Merged PRs (30d)
- 17
Description
The `#ordered/map` data literal constructs an invalid data structure when read in the REPL, but not when used in a `def` form.
### Minimal repro at the REPL:
```
$ clj -Sdeps '{:deps {org.flatland/ordered {:mvn/version "1.15.12"}}}'
Clojure 1.12.0
user=> (require '[flatland.ordered.map :as o])
nil
user=> (get (o/ordered-map [[:a 1]]) :a)
1
user=> (get #ordered/map [[:a 1]] :a)
Execution error (ClassCastException) at flatland.ordered.map.OrderedMap/valAt (map.clj:51).
class clojure.lang.PersistentVector cannot be cast to class clojure.lang.MapEntry (clojure.lang.PersistentVector and clojure.lang.MapEntry are in unnamed module of loader 'app')
```
### Extended repro as source file:
```clj
(ns repro (:require [flatland.ordered.map :as o])
(def m1 #ordered/map [[:a 1]])
(let [m #ordered/map [[:a 1]]]
(def m2 m))
(#(def m3 #ordered/map [[:a 1]]))
(keys m1) ;; => (:a)
(keys m2) ;; boom
(keys m3) ;; boom
(map class m1) ;; => (clojure.lang.MapEntry)
(map class m2) ;; => (clojure.lang.PersistentVector)
(map class m3) ;; => (clojure.lang.PersistentVector)
```
Something about Clojure's reader or this library's internals appears to be preventing the vectors from being cast into map entries or vice versa, causing the constructed object to be invalid and blow up when one tries to manipulate it.
The relevant data reader is
https://github.com/clj-commons/ordered/blob/b5315081f24858e3169923f0de6b9f08bc0dda5a/src/flatland/ordered/map.clj#L210
Note: it's possible to delay construction of the object to runtime as in the `ordered-map-reader-cljs`, but as hiredman pointed out in the linked Slack discussion, this would break the ability for macros to work with these ordered-map literals.
I attempted to fix it by having the reader explicitly cast to MapEntry, but this also fails:
```clj
(defn my-ordered-map-reader
"does not work!"
[coll]
(into (ordered-map)
(map (fn [[k v]] (clojure.lang.MapEntry/create k v)))
coll))
(set! *data-readers*
(assoc *data-readers* 'o/map #'my-ordered-map-reader))
(map class #o/map ([:a 1])) ;; => (clojure.lang.PersistentVector)
(keys #o/map ([:a 1])) ;; boom
```
More discussion and context at:
https://clojurians.slack.com/archives/C03S1KBA2/p1742444212617369
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.