It seems like, if you don't mind doing the assoc all the time, you could
replace the whole if with something like:
(assoc nu (:winner c) (or ((:winner c) nu) {:history [{}]}))
You might want to wrap that in a let so you don't repeat (:winner c).
Also, it looks like add-placeholder-to-history could be a map over an
update-in instead of a loop, like:
(defn prepend-hash [x]
(into [{}] x))
(defn add-placeholder-to-history [us]
(into {} (map #(update-in % [1 :history] prepend-hash) us)))
Chris
On Mon, May 25, 2015 at 5:07 PM, <[email protected]> wrote:
>
> I started to write an essay, aimed at those programmers who are
> experienced with highly mutable languages such as Javascript, Ruby, PHP,
> etc, to demonstrate how one's code style changes when one switches to a
> mostly immutable language such as Clojure. However, my Clojure code is not
> nearly as terse as I wanted. In particular, I have this nil check:
>
> (if (nil? ((:winner c) nu))
> (assoc nu (:winner c) {:history [{}]})
> nu)
>
> which I assume I am writing because I am ignorant. I'm guessing there
> might be something clever I can do to avoid this?
>
> For my code examples, I'm working with these 2 data structures:
>
> (def users {
> :henry {
> :history
> [
> {:housing 25, :restaurants 40, :theater 930},
> {:restaurants 30, :crisis 220}
> ]
> },
> :lisa {
> :history
> [
> {:theater 80},
> {:housing 445, :restaurants 15, :theater 35}
> ]
> },
> :pasha {
> :history
> [
> {:restaurants 5},
> {:restaurants 40, :theater 60}
> ]
> },
> :eli {
> :history
> [
> {:crisis 135, :restaurants 440, :theater 65},
> {:theater 95}
> ]
> }
> })
>
> (def contests [{:category :housing, :prize-money 100, :winner :eli},
> {:category :housing, :prize-money 30, :winner :henry},
> {:category :housing, :prize-money 340, :winner :henry},
> {:category :housing, :prize-money 45, :winner :susan},
> {:category :housing, :prize-money 15, :winner :henry},
> {:category :housing, :prize-money 10, :winner :pasha},
> {:category :housing, :prize-money 25, :winner :pasha},
> {:category :crisis, :prize-money 100, :winner :eli},
> {:category :crisis, :prize-money 2330, :winner :henry},
> {:category :crisis, :prize-money 90, :winner :henry},
> {:category :restaurants, :prize-money 1130, :winner :eli},
> {:category :restaurants, :prize-money 130, :winner :pasha},
> {:category :theater, :prize-money 60, :winner :eli},
> {:category :theater, :prize-money 90, :winner :pasha},
> {:category :theater, :prize-money 130, :winner :pasha},
> {:category :theater, :prize-money 830, :winner :susan},
> {:category :theater, :prize-money 90, :winner :susan},
> {:category :theater, :prize-money 270, :winner :eli}])
>
> Presumably "users" shows past winnings from 2 rounds of some contest,
> whereas "contests" shows the winnings from the 3rd round, which need to be
> added to "users". So I wrote:
>
>
> (defn add-placeholder-to-history [us]
> (loop [u us nu {}]
> (if (first u)
> (recur
> (rest u)
> (assoc nu (get (first u) 0) {:history (into [] (cons {}
> (:history (get (first u) 1))))}))
> nu)))
>
> (defn update-history [nu c]
> (update-in
> (if (nil? ((:winner c) nu))
> (assoc nu (:winner c) {:history [{}]})
> nu)
> [(:winner c) :history 0 (:category c)] (fnil #(+ %1 (:prize-money
> c)) 0)))
>
> And so in the end we would simply call:
>
> (reduce
> update-history
> (add-placeholder-to-history users)
> contests)
>
> Which correctly gives me:
>
> {
> :susan {
> :history [{:theater 920, :housing 45}]
> }
> :lisa {
> :history [{}
> {:theater 80}
> {:housing 445, :restaurants 15, :theater 35}]
> }
> :henry {
> :history [{:crisis 2420, :housing 385}
> {:housing 25, :restaurants 40, :theater 930}
> {:crisis 220, :restaurants 30}]
> }
> :eli {
> :history [{:theater 330, :restaurants 1130, :crisis 100, :housing 100}
> {:crisis 135, :restaurants 440, :theater 65}
> {:theater 95}]
> }
> :pasha {
> :history [{:theater 220, :restaurants 130, :housing 35}
> {:restaurants 5}
> {:restaurants 40, :theater 60}]
> }
> }
>
> And then I wrote:
>
> -----------------------------------
>
> By the way, you might be wondering what this is for:
>
> (if (nil? ((:winner c) nu))
> (assoc nu (:winner c) {:history [{}]})
> nu)
>
> We do this for Susan. She is a new contestant who won some money in the
> newest round of contests, however, she does not yet exist in "users", so we
> need to create a space for her. Without these 3 lines of code, we get this
> for her:
>
> {:susan {:history {0 {:theater 920, :housing 45}}},
>
> But with these 3 lines of code, we get the correct results for her, and
> for everyone else.
>
> -----------------------------------
>
> I am wondering if I can avoid those 3 lines of code?
>
>
>
>
> --
> 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/d/optout.
>
--
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/d/optout.