puniverse / pulsar

Fibers, Channels and Actors for Clojure
http://docs.paralleluniverse.co/pulsar/
Other
911 stars 53 forks source link

actors/receive with :after statement fails on some patterns #21

Closed dehubbed closed 10 years ago

dehubbed commented 10 years ago

The following example from the comments in the code to actors/receive fails: (receive :else m :after 30 :foo)

This is because :after statements, e.g. :after 20 :foo, have an odd number of expressions, so adding an :after statement turns a body with an otherwise even count of expressions into a body with an odd count. The assert-args statement https://github.com/puniverse/pulsar/blob/master/src/main/clojure/co/paralleluniverse/pulsar/actors.clj#L480 counts the expressions before removal of the :after statement, it should do so after, e.g. like so:

  ([& body]
   (let [[body after-clause] (if (= :after (nth-from-last body 2 nil)) (split-at-from-last 2 body) [body nil])
         _ (assert-args
              (or (even? (count body)) (vector? (first body))) "a vector for its binding")
         odd-forms   (odd? (count body))
dehubbed commented 10 years ago

Note that this coincidentally works with most :after statements since in the case of an odd number of body expressions the macro assumes the first expression is the optional binding vector. So this works if the first pattern is a vector. Vector-based patterns are common but not a requirement.

pron commented 10 years ago

@dehubbed Thank you!