这是惯用的代码吗?是否有更好或更简洁的方式来编写此代码?

时间:2020-07-13 17:49:44

标签: clojure

我正在尝试为扑克游戏建模。

我的游戏状态表示形式在地图中,对于这个问题,我仅对玩家感兴趣。

{:players {:1 {:money 200} :2 {money 400}}}

每个函数都具有游戏状态和一些其他参数,并返回新的游戏状态,例如:

(defn update-player-money
  "Returns new game state where player has added amount to his money"
  [game-state player amount]
  (assoc-in game-state [:players player :money]
            (+ (-> game-state :players player :money)
               amount)))

现在,我想要一个可以在传递新游戏状态的同时从每个玩家中移除一定金额的功能。 为了明确起见,两个玩家要做的事情:

(update-player-money (update-player-money game-state :1 (- 20)) :2 (-20))

这是我想出的:

(defn phase-1-blind
  "Removes blind from all players."
  [game-state blind-amount]
  (letfn [(blind-helper [game-state player-list amount]
            (if (seq player-list)
              (blind-helper (update-player-money game-state
                                                 (first player-list)
                                                 (- amount))
                            (rest player-list)
                            amount)
              game-state))]
  (blind-helper game-state (keys (:players game-state)) blind-amount)))

这行得通,但是我想知道是否还有一种更惯用或简洁的方法来达到相同的效果。

1 个答案:

答案 0 :(得分:2)

如果您想使用phase-1-blind实现update-player-money,则reduce在这里很有用:

(defn update-player-money
  "Returns new game state where player has added amount to his money"
  [game player-id amt]
  (update-in game [:players player-id :money] (fnil + 0) amt))

(defn phase-1-blind
  "Removes blind from all players."
  [game blind]
  (reduce #(update-player-money % %2 blind)
          game
          (keys (:players game))))

update-player-money中,fnil确保即使玩家没有使用:money键也不会破坏东西。