Welcome! Please see the About page for a little more info on how this works.

0 votes
in core.async by

I have an {{and}} condition inside a {{go}} block, where the two conditions take from channels.
When the first condition returns false, I would expect the second condition not to be checked at all. But, it is.

Here is the code:

`
(defn cc [x]
(go

 (println "cc: " x)

x))

(defn foo [x]

(go (when (and (= :ok (<! (cc x)))
               (= :ok (<! (cc 2))))
      (print "after and"))))

(foo 1)
(foo :ok)
`

When running {{(foo 1)}}, I would expect only {{cc: 1}} to be printed, but actually {{cc: 2}} is printed as well.

Happens only in ClojureScript, not in Clojure core.async.

5 Answers

0 votes
by

Comment made by: ashercoren

Note: This only happens in ClojureScript. In Clojure it works as expected.

Also, sorry for the poor formatting.. this is my first Jira issue.

0 votes
by

Comment made by: wxlite

Seems and works abnormal in many cases, not just with <!.
I tested this in:
clojure-1.8.0, clojurescript-1.7.228, core.async-0.2.374.
this test need nodejs with the request module.

(def request (js/require "request"))

Now I try to send request to an unaccessible site: google.
Yes, I can't use google.

`
(def result-chan (chan))

(request
"http://www.google.com"
(fn [err res body]

(go
  (if (and (not err) (= (.-statusCode res) 200))
    (>! result-chan body)
    (>! result-chan [])))))

`

the result should be "(link: )" (the request will timeout make "err" non-nil)

(go (println "result:" (<! result-chan)))

but actually I get:

                                    1.   _TypeError: Cannot read property 'statusCode' of undefined ..._ {color}

I have printed err and I am sure it's a JS object in this case, not nil or false. that's why res is undefined.
And it also means the short-circuit for and didn't work.
to make things right, use "if" instead of "and"

`
(def result-chan (chan))

(request
"http://www.google.com"
(fn [err res body]

(go
  (if (not err)
    (if (= (.-statusCode res) 200)
      (>! result-chan body)
      (>! result-chan []))
    (>! result-chan [])))))

`

then test it again:

(go (println "result:" (<! result-chan)))

work as expected now:

result: []

0 votes
by

Comment made by: zlorf

Well, the issue happens even for go-blocks without <!, and that is really strange. {{or}} is also affected. Here you have an example:

(go (if false (not= 404 (:status (println "SHOULD NOT BE PRINTED 1")))) ; ok (and false (not= 404 (:status (println "SHOULD NOT BE PRINTED 2")))) ; fail (or true (not= 404 (:status (println "SHOULD NOT BE PRINTED 2a")))) ; fail (if false (:status (println "SHOULD NOT BE PRINTED 3"))) ; ok (and false (:status (println "SHOULD NOT BE PRINTED 4"))) ; ok (or true (:status (println "SHOULD NOT BE PRINTED 4a"))) ; ok )

When you run this code snippet in Clojure, nothing gets printed (as expected).
In ClojureScript, however (tested with newest async version 0.3.443), you'll see {{SHOULD NOT BE PRINTED 2}} and {{2a}}.
Interesting observation: shorter computations (like example 4/4a) behave properly.

Like Wang Xing noticed: using if seems a safe way around this bug.

0 votes
by

Comment made by: zlorf

I suggest changing issue title to "(CLJS) and/or does not short-circuit in go"

0 votes
by
Reference: https://clojure.atlassian.net/browse/ASYNC-158 (reported by alex+import)
...