Clojure/Script pr-str/read-string roundtrip differences

763 views
Skip to first unread message

Thomas Heller

unread,
Jan 6, 2013, 7:13:30 PM1/6/13
to clo...@googlegroups.com
Hey,

I'm writing a Clojure Webapp with a CLJS Frontend and expected to be able to cljs.reader/read-string everything I pr-str'd on the CLJ side. That however does not work for defrecords and BigDecimals (1.1M) .

1. defrecord

In CLJ I can:

    (ns dummy)
    (defrecord Foo [bar])
    (pr-str (Foo. 1)) ; => "#dummy.Foo{:bar 1}"

in CLJS however this will print as

    "#Foo{:bar 1}"

missing the Namespace. I found an old post about this but no other information.

Also when I pr-str this record in CLJ and cljs.reader/read-string it in CLJS it fails with "Could not find tag parser for dummy.Foo in ("inst" "uuid" "queue") ", although the defrecord exists and is in the same ns (actually a cljsbuild crossover). I figured out that I can (cljs.reader/register-tag-parser! 'dummy.Foo make-foo) but thats seems faulty. I read about EDN and understand why the reader would think its reading a Tag but I can do read-string in CLJ just fine. Shouldnt both sides be equal here?

2. BigDecimals:

I understand that JavaScript has no BigDecimals and I can live with js/parseFloat on the Client for now, however is there any way I can hint the CLJS printer to print "1.1" as "1.1M"?

On the Topic of EDN: How would I "tag" a value in CLJ(S) to print {:foo "bar"} as #my/tag {:foo "bar"}? The docs only talk about data_readers.clj.

The answers probably lie in the sources, but I hope somebody here has a quick answer. ;)

Cheers,
/thomas

PS: I'd actually prefer using "tagged" literals instead of the defrecord constructor form since I dont trust anything coming from the client even it looks like clojure data. Is there some protocol I can implement for the record and have it print as tagged instead? For CLJ and CLJS? :)


David Nolen

unread,
May 9, 2013, 7:51:28 PM5/9/13
to clojure
Patch welcome for 1.

As far as 2 I myself see no way to make that work without considering a numerics overhaul.




--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Thomas Heller

unread,
May 9, 2013, 8:29:12 PM5/9/13
to clo...@googlegroups.com
Hey Brian,

been a while since that Post, Issue #1 has been resolved for a while (see http://dev.clojure.org/jira/browse/CLJS-466) but I actually switched to using proper EDN tags via IPrintWithWriter, clj/print-method and clojure.edn/read-string like you suggested.

#2 I solved indirectly via #1, I didnt find an acceptable BigDecimal JavaScript implementation and since all the math happens on the server anyways I just transmit them as Strings inside records. The Reader function in CLJS just keeps it as a String, the CLJ Reader function just does (BigDecimal. s) so all is good. (eg. #ns/money [:EUR "1234567.89"])




On Thu, May 9, 2013 at 9:03 PM, Brian Jenkins <bonk...@gmail.com> wrote:
Hi, Thomas.

I also found this frustrating. Here's a work-around I came up with:


;; assuming (defrecord Design [id name]) in namespace tektite.model.design
 
(cljs.reader/register-tag-parser!  "tektite.model.design.Design" tektite.model.design/map->Design)
 
(extend-protocol IPrintWithWriter
  tektite.model.design/Design
  (-pr-writer [coll writer opts]
    (let [pr-pair (fn [keyval] (pr-sequential-writer writer pr-writer "" " " "" opts keyval))]
      (pr-sequential-writer writer pr-pair "#tektite.model.design.Design{" ", " "}" opts coll))))


On the server side, I read EDN out of the request body with clojure.edn/read (because clojure.core/read is 
unsafe for reading evil strings from the internet).  clojure.edn/read doesn't pick up new readers
from data_readers.clj or *data-readers* (fortunately), but can be taught new tags like this:


(def model-readers {'tektite.model.design.Design #'tektite.model.design/map->Design})
 
(defn read-edn-body [context]
  (clojure.edn/read {:readers model-readers, :eof nil}
                    (java.io.PushbackReader.
                     (java.io.InputStreamReader.
                      (get-in context [:request :body])
                      "UTF-8"))))


(I use liberator, so the request arrives in a context hash)

Best,
Brian

On Monday, January 7, 2013 1:13:30 AM UTC+1, Thomas Heller wrote:
Hey,

I'm writing a Clojure Webapp with a CLJS Frontend and expected to be able to cljs.reader/read-string everything I pr-str'd on the CLJ side. That however does not work for defrecords and BigDecimals (1.1M) .

1. defrecord

In CLJ I can:

    (ns dummy)
    (defrecord Foo [bar])
    (pr-str (Foo. 1)) ; => "#dummy.Foo{:bar 1}"

in CLJS however this will print as

    "#Foo{:bar 1}"

missing the Namespace. I found an old post about this but no other information.

Also when I pr-str this record in CLJ and cljs.reader/read-string it in CLJS it fails with "Could not find tag parser for dummy.Foo in ("inst" "uuid" "queue") ", although the defrecord exists and is in the same ns (actually a cljsbuild crossover). I figured out that I can (cljs.reader/register-tag-parser! 'dummy.Foo make-foo) but thats seems faulty. I read about EDN and understand why the reader would think its reading a Tag but I can do read-string in CLJ just fine. Shouldnt both sides be equal here?

--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/4aeIxs_yNG4/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

David Nolen

unread,
May 9, 2013, 8:34:02 PM5/9/13
to clojure
Heh didn't notice the date on the first post :)


You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

Brian Jenkins

unread,
May 10, 2013, 12:35:03 PM5/10/13
to clo...@googlegroups.com
Doh!

I was running 0.0-1586 instead of 0.0-1798

Brian

On Monday, January 7, 2013 1:13:30 AM UTC+1, Thomas Heller wrote:

David Nolen

unread,
May 10, 2013, 12:48:43 PM5/10/13
to clojure
I believe 0.0-1806 is the latest.


Reply all
Reply to author
Forward
0 new messages