core.async

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

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Environment:
    core.async 0.1.338.0-5c5012-alpha

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.

Activity

Hide
Francis Avila added a comment -

CLJS-864 is likely the same issue. (It also has a small test project to reproduce.)

Show
Francis Avila added a comment - CLJS-864 is likely the same issue. (It also has a small test project to reproduce.)
Hide
Rangel Spasov added a comment -

This happened to me as well with the latest version of core.async on ClojureScript 0.2.395.

I would bump this to not minor since it severely breaks the promise that (and ...) makes.

(def cards :loading)
(go (and (vector? cards) (< 0 (count cards))))

This throws an exception like this:

No protocol method ICounted.-count defined for type cljs.core/Keyword: :loading

I was able to go around this by nesting the checks like this:
(go (if (vector? cards)
(if (< 0 (count cards))
(println "counting cards..."))))

Show
Rangel Spasov added a comment - This happened to me as well with the latest version of core.async on ClojureScript 0.2.395. I would bump this to not minor since it severely breaks the promise that (and ...) makes. (def cards :loading) (go (and (vector? cards) (< 0 (count cards)))) This throws an exception like this: No protocol method ICounted.-count defined for type cljs.core/Keyword: :loading I was able to go around this by nesting the checks like this: (go (if (vector? cards) (if (< 0 (count cards)) (println "counting cards..."))))
Hide
Mike Fikes added a comment - - edited

If you

(macroexpand '(go (and (vector? cards) (< 0 (count cards)))))

you will see that arguments to the js* special form are lifted out and let-bound, causing evaluation of code that the special form would never evaluate.

Show
Mike Fikes added a comment - - edited If you
(macroexpand '(go (and (vector? cards) (< 0 (count cards)))))
you will see that arguments to the js* special form are lifted out and let-bound, causing evaluation of code that the special form would never evaluate.

People

Vote (3)
Watch (2)

Dates

  • Created:
    Updated: