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
> <[email protected] <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 [email protected]<javascript:>
> > Note that posts from new members are moderated - please be patient with
> your
> > first post.
> > To unsubscribe from this group, send email to
> > [email protected] <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 [email protected] <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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.