Clojure. Intellij. Задержка. Параллельное. Clojure с нуля - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь выполнить упражнения в конце главы 6 Clojure с нуля . Вот что происходит со мной в самой первой проблеме ...

  (defn sum [start end] (delay (reduce + (range start end))))  ;; Define sum.
=> #'chapter6.core/sum

  (time (sum 0 1e7))  ;; Start sum but it delays, so almost no time elapses.
"Elapsed time: 0.2808 msecs"
=> #object[clojure.lang.Delay 0x2656db01 {:status :pending, :val nil}]

  (deref sum)  ;; Ask for the result. This should take some time. Only it doesn't. It errors right away.

Execution error (ClassCastException) at chapter6.core/eval1595 (form-init10872915734268438705.clj:1).
class chapter6.core$sum cannot be cast to class java.util.concurrent.Future (chapter6.core$sum is in unnamed module of loader cloju-re.lang.DynamicClassLoader @7c650722; java.util.concurrent.Future is in module java.base of loader 'bootstrap')

Я новичок. Я ничего не знаю о "bootstrap" или "модуле" или ... Что я делаю не так? Заранее спасибо. Кстати, есть ли «... с нуля» ответный ключ для упражнений?

Ответы [ 2 ]

2 голосов
/ 10 марта 2020

Сделайте это:

(deref (sum 0 1e7))

Ваша функция возвращает задержку только тогда, когда она вызывается . В (deref sum) ничто не вызывает его (и, действительно, вы никогда не предоставляете значения аргумента, было бы обязательно включать , если бы он вызывал ). Вместо этого вы пытаетесь разыменовать саму функцию sum, что недопустимо, поскольку функция не является задержкой.

0 голосов
/ 10 марта 2020

Детали легче увидеть, если вы создаете проект, а не работаете в REPL. Попробуйте добавить свой код в этот шаблон проекта :

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require [tupelo.misc :as misc]))

(defn sum
  [start end]
  (delay (reduce + (range start end))))  ;; Define sum.

(dotest
  (time (sum 0 1e7)) ;; Start sum but it delays, so almost no time elapses.
  (let [delay-val (sum 0 1e7)] ; sum returns a delay
    (spyxx delay-val)               ; print name & type of `delay-val`
    (time (deref delay-val))        ; `deref` forces the computation of the sum
    (spyxx (deref delay-val))       ; print expression & type
    ))

с результатом:

-------------------------------
   Clojure 1.10.1    Java 13
-------------------------------

Testing tst.demo.core

"Elapsed time: 0.140221 msecs"      ; from first `time`
delay-val => <#clojure.lang.Delay #object[clojure.lang.Delay 0x455cd186 {:status :pending, :val nil}]>

"Elapsed time: 189.021064 msecs"    ; from 2nd `time`
(deref delay-val) => <#java.lang.Long 49999995000000>  

В README больше документов и API документы .


Попробуйте добавить:

(spyxx sum)

, который производит:

sum => <#tst.demo.core$sum #object[tst.demo.core$sum 0x539edd3 "tst.demo.core$sum@539edd3"]>

Вот как Clojure «печатает» значение функции.


Если вы допустили ошибку, вы можете получить номер строки в сообщении об ошибке, которое очень помогает. Разыменование функции недопустимо, поэтому мы получаем ошибку:

(deref sum)   ; on line #17 of my file

производит:


ERROR in (dotest-line-9) (core.clj:2298)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.ClassCastException: class tst.demo.core$sum cannot be cast to class java.util.concurrent.Future (tst.demo.core$sum is in unnamed module of loader clojure.lang.DynamicClassLoader @67af3485; java.util.concurrent.Future is in module java.base of loader 'bootstrap')
 at clojure.core$deref_future.invokeStatic (core.clj:2298)
    clojure.core$deref.invokeStatic (core.clj:2320)
    clojure.core$deref.invoke (core.clj:2306)
    tst.demo.core$fn__21007.invokeStatic (core.clj:17) # ***** error line number *****
    tst.demo.core/fn (core.clj:9)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    <...snip...>



Обновление

Не забудьте включить эту строку в project.clj в :dependencies:

 [tupelo "0.9.198"]

См. этот шаблон проекта для примера.

...