2016년 12월 10일 토요일

[clojure] ref 사용하기



ref

이전 시간에 atom을 공부했다. 그런데 왜 ref라는게 필요할까? 값을 보호하는데 atom 하나만 있으면 되는거 아닌가? 하지만 여러개의 행위를 트랜잭션처럼 묶고싶다면? ref를 쓰는 것이 좋다.
user=> (def items
  #_=>   #{"backpack" "phone" "card" "water" "dairy"})
#'user/items
user=> (defn item-count [item count]
  #_=>   {:name item :count count})
#'user/item-count


user=> (def shelves (ref {:name "YH Market" :items 
         (set (map #(item-count % (rand-int 10)) items))}))
#'user/shelves
user=> shelves
#object[clojure.lang.Ref 0x7b5ff2de 
{:status :ready, :val {:name "YH Market", :items #{{:name "backpack", :count 0} 
{:name "card", :count 7} {:name "phone", :count 7} {:name "dairy", :count 8} 
{:name "water", :count 6}}}}]
user=> (:name shelves)
nil
user=> (:name @shelves)
"YH Market"
user=> (:items @shelves)
#{{:name "backpack", :count 0} {:name "card", :count 7} 
{:name "phone", :count 7} {:name "dairy", :count 8} {:name "water", :count 6}}

user=> (defn buy [shelves] (dosync
  #_=>   (when-let [goods (some #(if (> (:count %) 0) %) (:items @shelves))]
  #_=>     (let [updated-goods (item-count (:name goods) (dec (:count goods)))]
  #_=>       (alter shelves update-in [:items] disj goods)
  #_=>       (alter shelves update-in [:items] conj updated-goods)))))
#'user/buy
user=> (buy shelves)
{:name "YH Market", :items #{{:name "phone", :count 2} {:name "dairy", :count 8} 
{:name "card", :count 5} {:name "water", :count 6} {:name "backpack", :count 2}}}
user=> (buy shelves)
{:name "YH Market", :items #{{:name "phone", :count 1} {:name "dairy", :count 8} 
{:name "card", :count 5} {:name "water", :count 6} {:name "backpack", :count 2}}}
진열대를 만들고 거기에 item를 넣는다. 그리고 그 갯수는 임의로(0부터 10까지) 정했다. (buy shelves)로 하나를 사면? 하나가 사라진다. (문제는 대충 만들어서 물건을 고를 수 없음 ㅎㅎ..)

댓글 없음:

댓글 쓰기