Try if-some: https://clojuredocs.org/clojure.core/if-some

On Mon, May 25, 2015 at 4:07 PM, <lawre...@waleup.com> 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 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/d/optout.
>



-- 
“One of the main causes of the fall of the Roman Empire was that–lacking
zero–they had no way to indicate successful termination of their C
programs.”
(Robert Firth)

-- 
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/d/optout.

Reply via email to