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.

Reply via email to