Fork me on GitHub
#cljs-dev
<
2018-10-29
>
borkdude00:10:35

Could someone verify if this is a bug before I post it to JIRA? https://gist.github.com/borkdude/a7c38295f19a0dd2a68a7da21d634661

mfikes02:10:34

@borkdude Unfortunately, instrument and unstrument are side-effecting macros, and their behavior in the example above depends on when they are expanded. ClojureScript currently analyzes a finally block prior to the try body. Looking at Clojure's behavior for side-effecting macros, you can see that it expands macros in the try body prior to any in a finally block. ClojureScript could be revised to do things in that order, and, if such a revision were made, then the code above would work. Is this a bug? I suppose it depends on whether the Clojure language has anything to say about the ordering of macro expansion. If it does, it would probably make sense to have ClojureScript follow that where reasonable.

borkdude08:10:11

Thanks @mfikes. I made a workaround by not using finally, now I get why it works.

borkdude08:10:05

But just looking at the example, I’d say it’s a bug. It works with normal Clojure spec. Is there a way not using side effects in macros for cljs spec?

andy.fingerhut08:10:00

Even if ClojureScript analyzed the forms in the other order, wouldn't it do the unstrument side effect before executing the code, and still not work as desired? If so, it seems like this is a fundamental difference between ClojureScript and Clojure/Java in how instrument/unstrument are implemented between the two (functions in Clojure/Java, macros in ClojureScript).

andy.fingerhut08:10:41

clarification - macros with compile-time side effects in ClojureScript.

borkdude08:10:02

Andy: there seems to be a macro + runtime part to instrument/unstrument. When I avoid finally my code works as intended.

borkdude08:10:15

Note that instrument is used in a finally block somewhere in the .cljc code of spec cljs ( check-1).

borkdude09:10:33

I’ll post it to JIRA for the sake of documenting anyway

mfikes11:10:09

Yeah, @andy.fingerhut it is interesting the way it works. The (i|u)nstrumentation itself doesn't actually occur in the side effect, but some bookkeeping does, which causes the generated code to differ based on that bookkeeping. The generated code is what actually performs the (i|u)nstrumentation at runtime.

borkdude11:10:57

yeah and it seems that the bookkeeping can go out of sync with performing generated code

mfikes11:10:01

Independent of the semantics or lack thereof of this, the analysis order has the odd effects you might expect:

cljs.user=> (try
       #_=>  x
       #_=>  (catch :default _ y)
       #_=>  (finally z))
                      ^
WARNING: Use of undeclared Var cljs.user/z at line 4
WARNING: Use of undeclared Var cljs.user/y at line 3
WARNING: Use of undeclared Var cljs.user/x at line 2
(Note the decreasing line numbers.)