clj-commons / clj-commons/ordered

Issues with ordered/map data literals

Open
#77 6 comments 0 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.