我再次通过项目euler来开发和磨练我的核心技能。但是我理解类型检查器的输出有很多困难。我在阅读了几篇关于core.typed的介绍性资料以及关于core.typed wiki的一些信息之后问我。
我正在使用以下代码,请注意apply
的注释以及num
对函数euler3
中输入的映射无效。仍会生成错误消息。请忽略明显不良的factors
和prime?
函数。我选择了天真的实现,让我专注于类型注释。
(ns euler-clj.euler3
"Project euler problem 3.
Uses a very naive prime tester, would use a sieve or probabilistic
prime algorithm for a larger problem set.
What is the largest prime factor of the number 600851475143?"
(:require [clojure.core.typed :refer
[ann check-ns Int fn> non-nil-return Seq cf]]
[euler-clj.euler1 :as e1]))
(non-nil-return clojure.lang.Numbers/quotient :all)
(ann ^:no-check clojure.core/apply [[Number Number * -> Number] (Seq Number) -> Number])
(ann factors [Int -> (Seq Int)])
(defn factors
[n]
(filter (fn> [m :- Int] (e1/div-by m n)) (range 1 (inc (quot n 2)))))
; Very bad prime function, should be sieve/probabilistic.
; Also identifies 1 as prime incorrectly.
(ann prime? [Int -> Boolean])
(defn prime? [n] (= [1] (factors n)))
(ann euler3 [Int -> Number])
(defn euler3
[n]
(apply max (map num (filter prime? (factors n)))))
(ann -main [-> nil])
(defn -main
[]
(prn (euler3 600851475143)))
这会产生以下错误:
Type Error (euler-clj.euler3:26:3) Bad arguments to apply: Target: (Fn [java.lang.Number java.lang.Number * -> java.lang.Number]) Arguments: (clojure.core.typed/Seq java.lang.Number) in: (clojure.core/apply clojure.core/max (clojure.core/map clojure.core/num (clojure.core/filter euler-clj.euler3/prime? (euler-clj.euler3/factors n)))) ExceptionInfo Type Checker: Found 1 error clojure.core/ex-info (core.clj:4327) Start collecting euler-clj.euler3 Start collecting euler-clj.euler1 Finished collecting euler-clj.euler1 Finished collecting euler-clj.euler3 Collected 2 namespaces in 62.584894 msecs Start checking euler-clj.euler1 Checked euler-clj.euler1 in 165.76663 msecs Start checking euler-clj.euler3 Checked euler-clj.euler3 in 200.997234 msecs Checked 2 namespaces (approx. 60 lines) in 430.302357 msecs
我需要提供哪些类型的注释才能申请接受最大数量,然后接受这个数字序列?
由于
答案 0 :(得分:2)
首先,您不应为apply
提供自己的类型;它是在类型检查器中作为特殊情况实现的。
在这种情况下,core.typed需要一些说服力,max
永远不会被零参数调用。
这是一种方法:
(ann euler3 [Int -> Number])
(defn euler3
[n]
(let [[f & r] (map num (filter prime? (factors n)))]
(if f
(apply max f r)
(throw (Exception. "No prime factors")))))