This isn't idiomatic but can be useful for modeling mutable computations in 
pure functions:

(use '[blancas.morph core monads])
 
(def cards [{:balance 30} {:balance 25}])
(def due 100)
 
(run-state (mapm #(monad [due get-state
                          app (state (min due (:balance %)))
                          _   (put-state (- due app))]
                    (state (assoc % :applied-balance app))) cards) due)

mapm is a map for monads; (state x) boxes cards; the state is the total due.

;Pair([{:balance 30, :applied-balance 30} {:balance 25, :applied-balance 
25}],45)

On Thursday, May 2, 2013 8:34:41 PM UTC-7, Steven Degutis wrote:
>
> Epic win. Thanks guys, this is a really neat technique! I was thinking 
> the solution must be something like reduce but with two values, the 
> due amount and the cards, but I couldn't figure out how to get the 
> cards to "map". Turns out conj was the missing piece of the puzzle. 
> Thanks again! 
>
> On Thu, May 2, 2013 at 5:34 PM, Gavin Grover 
> <gavingro...@gmail.com <javascript:>> wrote: 
> > Is this code applying an amount due against a customer's list of credit 
> > cards? If so, there seems to be a bug. The third line should be: 
> > 
> >   card.appliedBalance = min(due, card.balance) 
> > 
> > and the Clojure code I'd write is: 
> > 
> >   (defrecord Card [balance applied-balance]) 
> > 
> >   (defn apply-due-to-cards [[due new-cards] card] 
> >     (let [applied-bal (min due (:balance card))] 
> >       [(- due applied-bal) 
> >        (conj new-cards (->Card (:balance card) applied-bal))])) 
> > 
> >   (assert (= 
> >     (reduce apply-due-to-cards [100 []] 
> >       [(->Card 10  0) (->Card 30  0) (->Card 150  0)]) 
> >     [0 
> >       [(->Card 10 10) (->Card 30 30) (->Card 150 60)]])) 
> > 
> > Also four lines long like the Ruby example, but it's easier to debug 
> when 
> > there's a bug just by changing `reduce` to `reductions`. It's also 
> > threadsafe, and can be parallelized for large datasets by using the 
> Clojure 
> > 5 Reducers library. 
> > 
> > 
> > On Friday, May 3, 2013 5:21:46 AM UTC+8, Steven Degutis wrote: 
> >> 
> >> Given pseudo-code (Ruby-ish): 
> >> 
> >> due = 100 
> >> cards = cards.map do |card| 
> >>     card.applied_balance = max(0, due - card.balance) 
> >>     due -= card.applied_balance 
> >> 
> >> Notice how due changes at each turn, and each successive item in 
> >> "cards" sees the change. 
> >> 
> >> What's an idiomatic way to do this in Clojure without using refs? 
> >> 
> >> -Steven 
> > 
> > -- 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "Clojure" group. 
> > To post to this group, send email to clo...@googlegroups.com<javascript:> 
> > Note that posts from new members are moderated - please be patient with 
> your 
> > first post. 
> > To unsubscribe from this group, send email to 
> > clojure+u...@googlegroups.com <javascript:> 
> > 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+u...@googlegroups.com <javascript:>. 
> > For more options, visit https://groups.google.com/groups/opt_out. 
> > 
> > 
>

-- 
-- 
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