clojure - 如何在 Clojure 中指定高阶函数参数?

标签 clojure higher-order-functions clojure.spec

假设我有一个函数,它接受一个函数并返回一个函数,该函数将给定的任何参数应用于传入的函数,并将结果放入向量中(这是一个简单的示例,但希望能说明我的观点)。

(defn box [f]
  (fn [& args]
    [(apply f args)]))

我认为盒子功能的规范看起来像这样

(spec/fdef box
  :args (spec/cat :function (spec/fspec :args (spec/* any?)
                                        :ret any?))
  :ret (spec/fspec :args (spec/* any?)
                   :ret (spec/coll-of any? :kind vector? :count 1)))

如果我随后检测盒子功能

(spec-test/instrument)

和 clojure.core/+ 的调用框,我得到一个异常

(box +)
ExceptionInfo Call to #'user/box did not conform to spec:
In: [0] val: ([]) fails at: [:args :function] predicate: (apply fn),  Cannot cast clojure.lang.PersistentVector to java.lang.Number
:clojure.spec.alpha/args  (#function[clojure.core/+])
:clojure.spec.alpha/failure  :instrument
:clojure.spec.test.alpha/caller  {:file "form-init4108179545917399145.clj", :line 1, :var-scope user/eval28136}
  clojure.core/ex-info (core.clj:4725)

如果我正确理解错误,那么它会采取任何?谓词并生成用于测试的 PersistentVector,这 clojure.core/+ 显然无法使用。这意味着我可以通过将框的参数函数规范更改为

(spec/fspec :args (spec/* number?)
            :ret number?)

但是如果我想对 clojure.core/+ 和 clojure.string/lower-case 使用 box 该怎么办?

注意为了让规范在 REPL 中工作,我需要

:dependencies [[org.clojure/clojure "1.9.0-alpha16"]]
:profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]]}}
:monkeypatch-clojure-test false

在project.clj和以下导入中

(require '[clojure.spec.test.alpha :as spec-test])
(require '[clojure.spec.alpha :as spec])

最佳答案

我认为你不能用 clojure.spec 来表达这个函数的类型。您需要type variables能够编写类似的内容(此处使用 Haskell 风格的签名)

box :: (a -> b) -> (a -> [b])

也就是说,能够“捕获”输入函数 f 的规范并将其部分内容包含在输出规范中非常重要。但据我所知,clojure.spec 中没有这样的东西。您还可以看到 clojure.spec 的 list of specs for built-in functions没有定义规范,例如 clojure.core/map,它也会有同样的问题。

关于clojure - 如何在 Clojure 中指定高阶函数参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45068107/

相关文章:

clojure - 将Clojure Spec与Datomic实体一起使用

python - Python 中更好的函数组合

java - 设置 Datomic 类路径函数以供 Windows 中的事务处理程序使用

python - 高阶函数(映射)

haskell - 什么是异态?

function - Scala 函数定义参数列表上的不同括号样式

Clojure 指定自然数

clojure - Clojure 中的可变参数函数错误

没有 Clojure 的计算机上的 Clojure?

clojure - 在将符号传递给 Clojure 中的宏之前,是否可以将符号解析为其值?