在clojure中传递布尔数组时性能不佳

在clojure中传递布尔数组时性能不佳,clojure,Clojure,我已经开始用clojure解决euler项目的问题,作为学习语言的一种手段。在为问题10实施eratosthenes筛选时,我最初体验到极低的性能,这似乎是由于传递了布尔数组。我发现我可以通过添加类型提示或重新排序代码来解决这个问题,以便帮助函数可以直接从父作用域访问布尔数组,但我不理解为什么需要它(type sieve)在任何帮助函数中返回[Z,因此clojure似乎已经知道它是一个布尔数组。有人能解释一下为什么这里需要类型提示吗 为代码墙道歉,我不知道在说明问题的同时可以删除哪些部分 ;;;

我已经开始用clojure解决euler项目的问题,作为学习语言的一种手段。在为问题10实施eratosthenes筛选时,我最初体验到极低的性能,这似乎是由于传递了
布尔数组
。我发现我可以通过添加类型提示或重新排序代码来解决这个问题,以便帮助函数可以直接从父作用域访问
布尔数组
,但我不理解为什么需要它
(type sieve)
在任何帮助函数中返回
[Z
,因此clojure似乎已经知道它是一个
布尔数组
。有人能解释一下为什么这里需要类型提示吗

为代码墙道歉,我不知道在说明问题的同时可以删除哪些部分

;;; returns a vector containing all primes smaller than limit
(defn gen-primes-orig [limit]
  (defn next-unmarked [sieve v]
    (loop [i (inc v)]
      (cond
       (>= i limit) nil
       (false? (aget sieve i)) i
       :true (recur (inc i)))))

  (defn mark-powers-of! [sieve v]
    (loop [i (+ v v)]
      (if (>= i limit) sieve
          (do
            (aset-boolean sieve i true)
            (recur (+ i v))))))

  (defn collect-primes [sieve]
    (loop [primes []
           i 0]
      (cond
       (>= i limit) primes
       (false? (aget sieve i)) (recur (conj primes i) (inc i))
       :true (recur primes (inc i)))))

  (let [sieve (boolean-array limit false)]
    ;; 0 and 1 are not primes
    (aset-boolean sieve 0 true)
    (aset-boolean sieve 1 true)

    (loop [v 0]
      (let [v (next-unmarked sieve v)]
        (if (nil? v) (collect-primes sieve)
            (do
              (mark-powers-of! sieve v)
              (recur v)))))))

(defn gen-primes-hint [limit]
  (defn next-unmarked [^booleans sieve v]
    ;; same body as in gen-primes-orig
    )
  (defn mark-powers-of! [^booleans sieve v]
    ;; same body as in gen-primes-orig
    )
  (defn collect-primes [^booleans sieve]
    ;; same body as in gen-primes-orig
    )
  (let [sieve (boolean-array limit false)]
    ;; same body as in gen-primes-orig
    ))

(defn gen-primes-letfn [limit]
  (let [sieve (boolean-array limit false)]
    ;; 0 and 1 are not primes
    (aset-boolean sieve 0 true)
    (aset-boolean sieve 1 true)

    (letfn [(next-unmarked [v]
              ;; same body as in gen-primes-orig
              )
            (mark-powers-of! [v]
              ;; same body as in gen-primes-orig
              )
            (collect-primes []
              ;; same body as in gen-primes-orig
              )]
      (loop [v 0]
        (let [v (next-unmarked v)]
          (if (nil? v) (collect-primes)
              (do
                (mark-powers-of! v)
                (recur v))))))))
这是三种混合物的运行时间。(结果已被删除。所有混合物产生相同、正确的结果。)


type
函数对传递的对象使用
.getClass
方法返回对象的类。也就是说,它使用运行时反射来计算对象的类。其中as-type提示通过避免生成基于反射的代码来帮助clojure编译器生成有效的代码。基本上
type
与帮助clojure编译器发出高效代码的类型提示无关。

好的,谢谢。我想clojure会使用类型推断来确定调用的正确类型。对于这种特定情况,难道不可能在编译时确定类型吗,因为函数是“内部”的,因此所有调用点都是已知的?
user> (time (apply + (gen-primes-orig  2000000)))
"Elapsed time: 108001.047327 msecs"
user> (time (apply + (gen-primes-hint  2000000)))
"Elapsed time: 2599.091978 msecs"
user> (time (apply + (gen-primes-letfn 2000000)))
"Elapsed time: 2768.060355 msecs"