(CLJS) 'and' does not short circuit within go block in clojurescript

Description

I have the following piece of ClojureScript code within a go block:

(cond
(and (vector? x) (= (first x) :some-key)) ...)

This generates the following piece of JavaScript code for the cond case:

if (40 === f) {
return
d = b[9],
f = cljs.core.vector_QMARK_.call(null, d),
d = cljs.core.first.call(null, d),
d = cljs.core.EQ.call(null, d, new cljs.core.Keyword(null, "some-key", "some-key", -978969032)),
cljs.core.truth_(f && d) ? b[1] = 42 : b[1] = 43,
new cljs.core.Keyword(null, "recur", "recur", -437573268);
}

This looks to me like both and arguments would actually get evaluated. As a result my code crashes whenever it hits this cond case and 'x' is not seqable.

Environment

core.async 0.1.338.0-5c5012-alpha

Activity

Show:
David Nolen
5 days ago

Fixed as of

David Nolen
5 days ago

The issue is in ClojureScript

Daniel Sutton
July 18, 2020, 10:57 PM

Possible fix in cljs to not optimize the and/or. ticket:

Daniel Sutton
June 27, 2020, 5:48 PM
Edited

another workaround is to split the check from the usage branch like so:

 

 

Daniel Sutton
June 27, 2020, 3:53 PM

its hard to read the output, but i think

 

(cljs.pprint/pprint (macroexpand '(go (and ^{:tag :dont-optimize} (vector? cards) (< 0 (count cards))))))

 

provides a workaround. The and macro checks to see if it can put all the logic into js with

 

Is a good approach to this problem figuring out a good way to prevent this optimization? If so, what would that look like?

Seem to be three options

  1. add information to env to prevent this optimization. Would require a change to cljs

  2. Walk the form to be expanded and remove boolean tags and seq tags such that the macroexpander thinks it can’t be done in javascripts notion of truthiness. Might be heavy-handed? Is the only downside just emitting a bit slower code?

  3. Prevent the boolean tag from being attached to the and forms? I’m not entirely sure

Won't Fix
Your pinned fields
Click on the next to a field label to start pinning.

Assignee

Unassigned

Reporter

import