Closed Grinkers closed 5 months ago
Wow, TIL clojure's read-string is actually quite powerful. It really is fully Extensible
.
(require '[clojure.edn :as edn]
'[clojure.string :as str]
'[cheshire.core :as json])
(defn parse-rust-nums [s]
(as-> s a
(str/split a #"_")
(apply str a)
(Integer/parseInt a)))
(def parsed-data
(edn/read-string
{:readers {'rust parse-rust-nums 'json #(json/parse-string %) 'keyword #(keyword %)}}
"[#json \"{\\\"cat\\\": 42}\" #rust \"123_456_221\" #keyword \"keyword with spaces\"]"))
;; (clojure.lang.PersistentArrayMap java.lang.Integer clojure.lang.Keyword)
(prn (map type parsed-data))
;; [{"cat" 42} 123456221 :keyword with spaces].
(prn parsed-data)
note that clojure actually supports keywords with spaces in them, even though it's not normally possible to type them in a repl directly with :
or edn-able with prn-str
(this is a particular clojure pet peeve of mine). A little custom reader can add support for this.
Will try to read with more attention this weekend
Original discussion in #141. I'm open to ideas. This will come after #95 and #141 for sure. I will let this sit in the back of my mind for some weeks/months. This seems really deep, like it might end up needing to almost reimplement clojure.
Off-spec
https://github.com/edn-format/edn?tab=readme-ov-file#tagged-elements I think the current implementation doesn't follow the spec. I believe we shouldn't have a Tagged type at all (and certainly not a
(String, Edn)
). An interesting thing to note is that I believe this is lossy. In my#foo
and#bar
examples, after theread-string
, the tag is actually losthttps://github.com/edn-rs/edn-rs/blob/d64f20c3079268372970398349ae5bf5b7b40f41/tests/deserialize.rs#L716 This should throw an error without any custom readers.
Idea 1 (seems bad)
Clojure has a couple ways to define custom readers. One can be seen https://clojuredocs.org/clojure.core/data-readers Rust doesn't have a great way to dynamically do this. That would require creating Edn instances, mutating/registering them, pointers/lifetimes, etc. It would be a horrible mess to use.
Idea 2
The other way can be seen in this example
I think we could do something like this in rust
Idea 3
Agree this is insane and just keep the current implementation and leave it as an exercise for the user. Alternatively, we can feature gate Tagged, so people who need it to not be lossy can opt-in, but mark it as unstable/off-spec.