based on what you posted to stack overflow I would guess it's because the side-effects (the prints) are coming too soon---you have a println as the first line of check-k-v, so if the expression (mplus (check-k-v ...) (check-k-v ...)) is evaluated, then, given that mplus is not a macro, both arguments will be evaluated, and both prints will happen.
Since the state modifications aren't both happening, I assume that the actual computation returned---the domonad block---is being correctly treated. On Tue, Oct 22, 2013 at 4:23 AM, Mark Fisher <mark.j.fis...@gmail.com>wrote: > I originally posted this in Stack > Overflow<http://stackoverflow.com/questions/19505334/clojure-algo-monad-strange-m-plus-behaviour-with-parser-m-why-is-second-m-plus>, > but realised I might get more response from the google group. Apologies for > duplication. > > I'm seeing some issues using a parser monad created from the state monad > transformer. > > I've written a full test case on the SO page outlining the issue, which is > that when I use m-plus for the combined monad, it always evaluates the > first 2 methods, even though it uses the return values from the first (if > it is valid), and any state changes in the second occur but are discarded > (however side effects do - like d/b updates etc). > > e.g. > > (def parser-m (state-t maybe-m)) > (def world-destroyer > (domonad parser-m > [_ (fetch-state) > result (m-plus > (check-we-are-chilled) > (destroy-planet))] > result)) > (world-destroyer {:chill-out true}) > > In this implementation, destroy-planet is always evaluated. > Both of these monadic functions can terminate by using a :when condition > on the state. > > If I add a dummy method to the m-plus call list at the start (as first or > as second method in list) that does nothing (using a :when nil predicate to > stop its evaluation), the results are fine, no planet is destroyed because > it's never called, and the dummy monadic function takes the hit of stopping > m-plus spilling into the destroy-planet function. > > Interestingly, any state changes I make in the method erroneously called > do not get reflected in the final return value (clearly due to immutability > of the state map), but side effects are happening - and that's my issue. > > I've reverted to using a hand-crafted parser-m as given on Jim Duey's > monad blog <http://www.intensivesystems.net/tutorials/monads_101.html> which > doesn't exhibit this behaviour. > > I'm relatively inexperienced with clojure and monads (I was using this as > an excuse to learn them both), so I thought i'd try and work out why it's > happening. > > From looking at the definitions of state-t monad-m, the only thing i can > see m-plus doing different to Jim's version is: > > state-t monad-m: > (defn x [s] > (apply (fn [& xs] > (first (drop-while nil? xs))) > (map #(% s) flist))) > > jim's: > (defn y [s] > (first (drop-while nil? > (map #(% s) flist)))) > > for some list of functions flist, e.g. > (def flist > [(fn [x] > (println "f a : " x) > (when-let [r (:a x)] r)) > (fn [x] > (println "f b: "x) > (when-let [r (:b x)] r)) > (fn [x] > (println "f nil : " x) > nil)]) > > (x {:b 2}) > (y {:b 2}) > > and running either of these produces same result (2), however they both > produce the println side effects of *all 3* functions in the list, so now > i'm even more confused. > > I thought everything in y is lazy, so only the first two methods would be > used from the array. I can't find anything saying apply is lazy, so thought > I was getting closer. > > Anyone have any thoughts on this? Am I using m-plus in the right way > inside a domonad call? > > Cheers, > Mark > > -- > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > -- Ben Wolfson "Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure." [Larousse, "Drink" entry] -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.