core.async

Faulty rebinding of loop bindings in go macro

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code and Test

Description

Below from https://groups.google.com/d/msg/clojure/MJc-69TgjR0/9HZqE7-kM9UJ

There seems to be an issue with the rebinding of loop-bindings using loop/recur in go blocks,
specifically when you are just changing the order of the original bindings in a recur call.

Take this snippet for example:
(require '[clojure.core.async :refer [go timeout]])
(go (loop [a :black, b :white]
(println a b)
(<! (timeout 1000))
(recur b a)))

Instead of repeatedly printing

:black :white
:white :black
:black :white
:white :black
(...)

it actually prints

:black :white
:white :white
:white :white
:white :white
(...)

Note however, that

(require '[clojure.core.async :refer [go timeout]])
(go (loop [a :black, b :white]
(println a b)
(<! (timeout 1000))
(recur (identity b) (identity a))))

works correctly.

Activity

Hide
Ghadi Shayban added a comment -

fixed with tests + cljs port.

Show
Ghadi Shayban added a comment - fixed with tests + cljs port.
Hide
Ghadi Shayban added a comment -

Root cause:
Recurring with (recur b a) will emit semantically invalid code.
essentially
(let [b a
a b]

instead of something like:
(let [temp-b b
b a
a b]

Preliminary patch is on branch ASYNC-16.

TODO: add basic test and port the patch to cljs

Show
Ghadi Shayban added a comment - Root cause: Recurring with (recur b a) will emit semantically invalid code. essentially (let [b a a b] instead of something like: (let [temp-b b b a a b] Preliminary patch is on branch ASYNC-16. TODO: add basic test and port the patch to cljs

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: