【发布时间】:2018-07-22 01:58:50
【问题描述】:
经常发生的情况是,我有一个函数,它接受一些可选参数并将它们传递给其他函数,这些函数将它们进一步向下传递到堆栈,依此类推。如果没有我在下面说明的容易出错的复杂性类型,如何在 Clojure 中做到这一点?
-
如果你直接传递 optional-argument 变量,被调用者不能接受它作为可选参数:
(defn func1 [& {:keys [n-iterations] :or {n-iterations 20} :as opts}] (println "func1:" n-iterations) (func2 opts)) (defn func2 [& {:keys [n-iterations]}] (println "func2:" n-iterations)) user=> (func1 :n-iterations 15) func1: 15 IllegalArgumentException No value supplied for key: {:n-iterations 15} clojure.lang.PersistentHashMap.create (PersistentHashMap.java:77) -
如果调用者需要可选参数作为非可选的 map 参数,这很丑陋且容易出错,而且最重要的是,它会丢失默认值:
(defn func2 [{:keys [n-iterations]}] ;lost the & (println "func2:" n-iterations)) user=> (func1 :n-iterations 15) func1: 15 func2: 15 nil user=> (func1) func1: 20 func2: nil nil我听说您应该在顶层采用可选参数,在堆栈的所有较低级别采用非可选映射。但是,我发现这并不令人满意,因为通常,尤其是在 REPL 中,我想在任何“级别”调用任何函数,而不管是否有其他函数调用它。有一个统一的调用约定很有帮助。
-
如果您转发调用者未提供的可选参数,Clojure 会将其转换为 nil,然后在堆栈的每一步将其包装在 ArraySeq 中:
(defn func1 [& opts] (println "func1:" opts) (func2 opts)) (defn func2 [& opts] (println (type opts)) (println "func2:" opts) (func3 opts)) (defn func3 [& opts] (println "func3:" opts)) user=> (func1) func1: nil func2: (nil) func3: ((nil))
大多数 Clojure 功能对我来说都非常顺利,但事实并非如此。这样做的正确方法是什么?
以上都是Clojure 1.9.0下的。
【问题讨论】:
标签: clojure parameter-passing optional-parameters