rewrite-clj

Ivar Refsdal 2022-05-16T11:59:58.507939Z

I noticed a strange behaviour with z/assoc:

; As expected:
(-> (z/of-string "{}") (z/assoc :demo "string-value"))
=> [<map: {:demo "string-value"} > {:l [], :pnodes [<forms: {} >], :ppath nil, :r nil, :changed? true}]

; Quoting something gives a strange map:
(-> (z/of-string "{}") (z/assoc :demo "\"quoted\""))
=> [<map: {:demo "", quoted ""} > {:l [], :pnodes [<forms: {} >], :ppath nil, :r nil, :changed? true}]

; I would expect this:
(-> (z/of-string "{:demo \"\\\"quoted\\\"\" }"))
=> [<map: {:demo "\"quoted\""} > {:l [], :pnodes [<forms: {:demo "\"quoted\""} >], :ppath nil, :r nil}]
Or do I need to wrap the value to z/assoc in something? Edit1: Typos and: Thanks for a great library! Edit2: I'm using 1.0.767-alpha.

lread 2022-05-16T14:11:21.102339Z

Hiya @ivar.refsdal thanks for your question! I’ll fire up a REPL soon and take a look.

❤️ 1
Ivar Refsdal 2022-05-17T17:32:55.710569Z

Thanks for following up, and looking forward to a fix in the future 🙂

👍 1
lread 2022-05-16T14:46:24.177019Z

@ivar.refsdal Ok I’ll start with rerunning your example from a plain old clj repl.

user=> (require '[rewrite-clj.zip :as z])
nil
user=> (-> (z/of-string "{}") (z/assoc :demo "string-value"))
[<map: {:demo "string-value"}> {:l [], :pnodes [<forms: {}>], :ppath nil, :r nil, :changed? true}]
user=> (-> (z/of-string "{}") (z/assoc :demo "\"quoted\""))
[<map: {:demo ""quoted""}> {:l [], :pnodes [<forms: {}>], :ppath nil, :r nil, :changed? true}]
user=> (-> (z/of-string "{:demo \"\\\"quoted\\\"\" }"))
[<map: {:demo "\"quoted\"" }> {:l [], :pnodes [<forms: {:demo "\"quoted\"" }>], :ppath nil, :r nil}]
The first thing I’m noticing is that our outputs for (-> (z/of-string "{}") (z/assoc :demo "\"quoted\"")) are different. To make sure we are on the page, can you rerun on your side and see if there is a difference?

lread 2022-05-16T14:49:10.335429Z

I’m gonna guess something formatted your output weird and that we are on the same page.

lread 2022-05-16T14:50:42.832109Z

So, I think maybe the issue is that you are expecting strings to the same as reading from a file?

lread 2022-05-16T14:54:53.853829Z

The string "string-value" is internally the string string-value The string "\"quote\"" is internally the string "quoted" And those are what will be seen by rewrite-clj.

lread 2022-05-16T14:55:38.040289Z

I could be entirely missing your question though, lemme know if that makes any sense.

Ivar Refsdal 2022-05-16T18:39:39.432199Z

You are right in that the formatted output is weird in some way. It also works on the console for me (but not in IntelliJ/Cursive). However, here is a related problem (?)/thing I don't understand:

(-> "{}" z/of-string (z/assoc :demo "here is a quote:\". End.") (z/root-string))
=> "{:demo \"here is a quote:\". End.\"}"
I also tried with the example from the user guide: https://github.com/clj-commons/rewrite-clj/blob/main/doc/01-user-guide.adoc#finding-elements-with-the-zip-api and replaced
(-> zloc-desc (z/replace "My first Project.") z/root-string println)
with
(-> zloc-desc (z/replace "Project with a quote: \". A quote.") z/root-string println)
It outputs:
(defproject my-project "0.1.0-SNAPSHOT"
              :description "Project with a quote: ". A quote.")
There is something wrong, no? (Or am I just confused maybe?)

Ivar Refsdal 2022-05-16T18:40:21.022269Z

Thanks for your time and reply 🙂

Ivar Refsdal 2022-05-16T18:45:25.081199Z

1.0.767-alpha does not do it properly (I think!):

$ clj -Sdeps '{:deps {rewrite-clj/rewrite-clj {:mvn/version "1.0.767-alpha"}}}' -e '(do
(require (quote [rewrite-clj.zip :as z])) 
(-> (z/of-string "{}") 
    (z/assoc :demo "and a quote: \". <- A quote.")
    (z/root-string)
    (println))
)'
WARNING: Implicit use of clojure.main with options is deprecated, use -M
{:demo "and a quote: ". <- A quote."}
whereas 0.6.1 does it correctly:
$ clj -Sdeps '{:deps {rewrite-clj/rewrite-clj {:mvn/version "0.6.1"}}}' -e '(do
(require (quote [rewrite-clj.zip :as z])) 
(-> (z/of-string "{}") 
    (z/assoc :demo "and a quote: \". <- A quote.")
    (z/root-string)
    (println))
)'
WARNING: Implicit use of clojure.main with options is deprecated, use -M
{:demo "and a quote: \". <- A quote."}

Ivar Refsdal 2022-05-16T18:49:38.180299Z

Head has same behaviour as .767:

$ clj -Sdeps '{:deps {rewrite-clj/rewrite-clj {:git/url "" :sha "0bf3ee3ac625738f7fa3e5e163039e1bcf47fff2"}}}' -e '(do
(require (quote [rewrite-clj.zip :as z])) 
(-> (z/of-string "{}") 
    (z/assoc :demo "and a quote: \". <- A quote.")
    (z/root-string)
    (println))
)'
Cloning: 
Checking out:  at 0bf3ee3ac625738f7fa3e5e163039e1bcf47fff2
WARNING: Implicit use of clojure.main with options is deprecated, use -M
{:demo "and a quote: ". <- A quote."}

lread 2022-05-16T19:22:45.600479Z

> Thanks for your time and reply 🙂 My pleasure!

lread 2022-05-16T19:26:46.542419Z

Thanks for comparing against v0.6.1, that is interesting. I’m more confused, frankly, by 0.6.1 behaviour than 1.0.767 behaviour. I’ll take a deeper look.

lread 2022-05-16T19:39:25.532939Z

So more narrowed down to the coercion, we can see the difference: v1

❯ clj -Sdeps '{:deps {rewrite-clj/rewrite-clj {:mvn/version "1.0.767-alpha"}}}'        
Clojure 1.11.1
user=> (require '[rewrite-clj.node :as n])
nil
user=> (n/coerce "hey \" man")
<token: "hey " man">
v0
❯ clj -Sdeps '{:deps {rewrite-clj/rewrite-clj {:mvn/version "0.6.1"}}}'        
Clojure 1.11.1
user=> (require '[rewrite-clj.node :as n])
nil
user=> (n/coerce "hey \" man")
<token: "hey \" man">
I’ll pinpoint what change made v1 do things differently.

lread 2022-05-16T19:59:44.567669Z

Raised an isssue: https://github.com/clj-commons/rewrite-clj/issues/176

lread 2022-05-16T20:35:36.362769Z

@borkdude would you mind having a peek and sharing your opinion on the issue? My current feeling is that I unknowingly (at least I don’t remember) fixed an issue in v0.

borkdude 2022-05-16T20:42:51.723939Z

@lee Will do later this week!

borkdude 2022-05-16T20:43:53.397769Z

Isn't this just the printing behavior?

lread 2022-05-16T20:45:08.032639Z

That’s what I thought at first, but am now convinced otherwise.

lread 2022-05-16T20:45:52.260839Z

Looks like v0 effectively escaped " in strings when coercing.

lread 2022-05-16T20:46:54.697479Z

Which seems wrong to me, but wanted a borkpinion.

2
borkdude 2022-05-16T20:47:23.744639Z

yeah, that seems wrong to me too

borkdude 2022-05-16T20:48:02.410359Z

I would expect it to print <token: "hey \" man"> though

borkdude 2022-05-16T20:48:22.818349Z

although, maybe the nodes don't use prn but println style ?

lread 2022-05-16T20:50:31.965909Z

yeah nodes override default pr with a println style.

borkdude 2022-05-16T20:51:29.317699Z

ok, in that case I would say v1 makes more sense

lread 2022-05-16T20:51:38.867069Z

I thought so too.

lread 2022-05-16T20:52:05.735119Z

I don’t know that v0 meant to do what it was doing there.

lread 2022-05-16T21:33:38.010799Z

Update examples in https://github.com/clj-commons/rewrite-clj/issues/176 to use pr to make things clearer (even to me!). We are wrapping a string in " so we need to wrap any inner " (I’ve flip flopped and now think rewrite-clj v0 is correct).

borkdude 2022-05-16T21:36:01.212999Z

yes, agreed

lread 2022-05-16T21:39:07.779249Z

So @ivar.refsdal, it took my a while to get there, but I finally understand! Thanks so much for raising this, I’ll follow up with a fix sometime soon.

lread 2022-05-16T23:24:38.171359Z

(and also thanks @borkdude, as usual!)