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.

Reply via email to