【问题标题】:Clojure: succinctly forward optional valuesClojure:简洁地转发可选值
【发布时间】:2023-03-14 22:29:01
【问题描述】:

我在 Clojure 中编写了一个概率函数,它采用可选的选项哈希映射:

(defn roll-lte
  ([n d] (/ n d))
  ([n d options]
    (let [p (/ n d)
          roll-type (:type options :normal)]
      (cond
        (= roll-type :advantage) (- (* p 2) (* p p))
        (= roll-type :disadvantage) (* p p)
        (= roll-type :normal) p
        :else (throw (IllegalArgumentException. "Invalid roll type."))))))

这按预期工作,但其想法是编写基于此的其他函数——例如:

(defn roll-gte
  ([n d] (roll-lte (- d n -1) d))
  ([n d options] (roll-lte (- d n -1) d options)))

roll-lte 中的两个参数使函数的构建变得尴尬和重复,尤其是在上述情况下,options 只是被转发到roll-lte。有没有更简洁、更少重复的方法来实现这一点?

【问题讨论】:

    标签: clojure optional-parameters optional-arguments


    【解决方案1】:

    当我有具有多个元数的函数时,我通常会尝试让较低元数的版本使用安全的默认参数调用较高元数的版本。函数的“主要”实现通常最终是最高元数的主体:

    (defn roll-lte
      ([n d] (roll-lte n d nil))
      ([n d {:keys [type]
             :or   {type :normal}}]
       (let [p (/ n d)]
         (case type ;; used case instead of cond here
           :advantage (- (* p 2) (* p p))
           :disadvantage (* p p)
           :normal p
           (throw (IllegalArgumentException. "Invalid roll type."))))))
    

    我还在上面的选项映射解构中使用了:or 来设置type 的默认值,这允许较低参数的函数只传递一个零选项映射。

    (defn roll-gte
      ([n d] (roll-gte n d nil))
      ([n d options] (roll-lte (- d n -1) d options)))
    
    (roll-gte 3 4) ;=> 1/2
    (roll-gte 3 4 {:type :advantage}) ;=> 3/4
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      相关资源
      最近更新 更多