调用 clojure.core/fn 不符合规范

Call to clojure.core/fn did not conform to spec

我收到这条消息:

Exception in thread "main" clojure.lang.ExceptionInfo: Call to clojure.core/fn did not conform to spec: In: [0] val: (- (int p1__148#) 48) fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector? In: [0 0] val: - fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-n :args] predicate: vector? #:clojure.spec.alpha{:problems ({:path [:args :bs :arity-1 :args], :pred clojure.core/vector?, :val (- (int p1__148#) 48), :via [:clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [0]} {:path [:args :bs :arity-n :args], :pred clojure.core/vector?, :val -, :via [:clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [0 0]}), :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x58faa93b "clojure.spec.alpha$regex_spec_impl$reify__2436@58faa93b"], :value ((- (int p1__148#) 48) [x] (* x x)), :args ((- (int p1__148#) 48) [x] (* x x))}, compiling:(/Users/hassan/Desktop/fourclojure/src/fourclojure/120.clj:8:31) at clojure.lang.Compiler.checkSpecs(Compiler.java:6891) at clojure.lang.Compiler.macroexpand1(Compiler.java:6907) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6989) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6991) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyze(Compiler.java:6729) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6100) at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5460) at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4022) at clojure.lang.Compiler.analyzeSeq(Compiler.java:7001) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyze(Compiler.java:6729) at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3881) at clojure.lang.Compiler.analyzeSeq(Compiler.java:7005) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyze(Compiler.java:6729) at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3881) at clojure.lang.Compiler.analyzeSeq(Compiler.java:7005) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6991) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyze(Compiler.java:6729) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6100) at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5460) at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4022) at clojure.lang.Compiler.analyzeSeq(Compiler.java:7001) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6991) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.access0(Compiler.java:38) at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:595) at clojure.lang.Compiler.analyzeSeq(Compiler.java:7003) at clojure.lang.Compiler.analyze(Compiler.java:6773) at clojure.lang.Compiler.analyze(Compiler.java:6729) at clojure.lang.Compiler.eval(Compiler.java:7066) at clojure.lang.Compiler.load(Compiler.java:7514) at clojure.lang.Compiler.loadFile(Compiler.java:7452) at clojure.main$load_script.invokeStatic(main.clj:278) at clojure.main$script_opt.invokeStatic(main.clj:338) at clojure.main$script_opt.invoke(main.clj:333) at clojure.main$main.invokeStatic(main.clj:424) at clojure.main$main.doInvoke(main.clj:387) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.lang.Var.applyTo(Var.java:702) at clojure.main.main(main.java:37) Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/fn did not conform to spec: In: [0] val: (- (int p1__148#) 48) fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector? In: [0 0] val: - fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-n :args] predicate: vector? {:clojure.spec.alpha/problems ({:path [:args :bs :arity-1 :args], :pred clojure.core/vector?, :val (- (int p1__148#) 48), :via [:clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [0]} {:path [:args :bs :arity-n :args], :pred clojure.core/vector?, :val -, :via [:clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [0 0]}), :clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x58faa93b "clojure.spec.alpha$regex_spec_impl$reify__2436@58faa93b"], :clojure.spec.alpha/value ((- (int p1__148#) 48) [x] (* x x)), :clojure.spec.alpha/args ((- (int p1__148#) 48) [x] (* x x))} at clojure.core$ex_info.invokeStatic(core.clj:4739) at clojure.core$ex_info.invoke(core.clj:4739) at clojure.spec.alpha$macroexpand_check.invokeStatic(alpha.clj:689) at clojure.spec.alpha$macroexpand_check.invoke(alpha.clj:681) at clojure.lang.AFn.applyToHelper(AFn.java:156) at clojure.lang.AFn.applyTo(AFn.java:144) at clojure.lang.Var.applyTo(Var.java:702) at clojure.lang.Compiler.checkSpecs(Compiler.java:6889) ... 45 more

当我运行这段代码时:

(defn count-less-than-square [l]
  (->>
   l
   (map (fn [n] (->> n
                     str
                     (map #(-> % int (- 48) (fn [x] (* x x)))) ; The problem is that fn
                     (reduce +)
                     (list n))))
   (filter #(< (first %) (second %)))
   count))

然而,当我运行它是这样的:

(defn pow [a b] (reduce * 1 (repeat b a)))

(defn count-less-than-square [l]
  (->>
   l
   (map (fn [n] (->> n
                     str
                     (map #(-> % int (- 48) (pow 2)))
                     (reduce +)
                     (list n))))
   (filter #(< (first %) (second %)))
   count))

(pp/pprint (count-less-than-square (range 30)))

它工作正常。

为什么 (fn [x] (* x x)) 崩溃了?它在 REPL 中运行良好。

问题是您正在使用的 -> 宏将线程值插入第一个位置,就在 fn 符号之后。 所以这个:

(map #(-> % int
          (- 48)
          (fn [x] (* x x))))

变成类似:

(map #(fn
        (- (int %) 48)
        [x]
        (* x x)))

这显然是无效的,因为 fn 期望第一个 arg 是函数参数的向量,这就是错误消息试图说明的内容:

fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector?