2014-12-27 3 views
1

Я хотел бы понять, почему я не могу добавить аннотацию возвращаемого типа к этой функции продукта точки в clojure.Почему аннотация этого типа не подходит?

(defn dot3 
    "3d vector dot product" 
    ^double [^doubles [u0 u1 u2] 
      ^doubles [v0 v1 v2]] 
    (+ (* u0 v0) (* u1 v1) (* u2 v2))) 

В журнале ниже вы можете увидеть, что аннотация для вычитания работает просто отлично, и если я удалить аннотацию типа ^double возврата также работает. Но приведенный выше код выдает ошибку при вызове:

user=> (dot3 [4 5 6] [1 2 3])  
ClassCastException user$dot3 cannot be cast to clojure.lang.IFn$OOD user/eval3487 (form-init8441686871120943013.clj:1) 

Спасибо заранее,

--Roger

thunder 13:17:21 clojure> lein version 
Leiningen 2.5.0 on Java 1.8.0_25 Java HotSpot(TM) 64-Bit Server VM 
thunder 13:17:28 clojure> lein new test123 
Generating a project called test123 based on the 'default' template. 
The default template is intended for library projects, not applications. 
To see other templates (app, plugin, etc), try `lein help new`. 
thunder 13:18:09 clojure> cd test123 
thunder 13:18:14 test123> lein repl 
nREPL server started on port 57240 on host 127.0.0.1 - nrepl://127.0.0.1:57240 
REPL-y 0.3.5, nREPL 0.2.6 
Clojure 1.6.0 
Java HotSpot(TM) 64-Bit Server VM 1.8.0_25-b17 
    Docs: (doc function-name-here) 
      (find-doc "part-of-name-here") 
    Source: (source function-name-here) 
Javadoc: (javadoc java-object-or-class-here) 
    Exit: Control+D or (exit) or (quit) 
Results: Stored in vars *1, *2, *3, an exception in *e 

user=> (defn vsub3 
    #_=> "3d vector subtraction" 
    #_=> ^doubles [^doubles [u0 u1 u2] 
    #_=>    ^doubles [v0 v1 v2]] 
    #_=> [(- u0 v0) (- u1 v1) (- u2 v2)]) 
#'user/vsub3 
user=> (vsub3 [4 5 6] [1 2 3]) 
[3 3 3] 
user=> (defn dot3 
    #_=> "3d vector dot product" 
    #_=> ^double [^doubles [u0 u1 u2] 
    #_=>   ^doubles [v0 v1 v2]] 
    #_=> (+ (* u0 v0) (* u1 v1) (* u2 v2))) 
#'user/dot3 
user=> (dot3 [4 5 6] [1 2 3]) 
ClassCastException user$dot3 cannot be cast to clojure.lang.IFn$OOD user/eval3487 (form-init8441686871120943013.clj:1) 
user=> (defn dot3 
    #_=> "3d vector dot product" 
    #_=> [^doubles [u0 u1 u2] 
    #_=> ^doubles [v0 v1 v2]] 
    #_=> (+ (* u0 v0) (* u1 v1) (* u2 v2))) 
#'user/dot3 
user=> (dot3 [4 5 6] [1 2 3]) 
32 
+1

FYI, когда вы предоставляете неверную аннотацию, предупреждение отражения на компиляции исчезнет, ​​но вы все равно платите стоимость процессора для выполнения отражения, так как типы были неправильными. Для аннотации '^ doubles' аргумент должен иметь тип' '[D;" '(примитивный массив double), а не PersistentVector of Long. – noisesmith

ответ

1

Тип аннотаций вы предоставили несовместима с тем, как вы укажете аргументы функции.

Деструктурирование предотвращает компиляцию надлежащего кода. Оказывается, это ошибка в текущих версиях Clojure, но будет исправлена ​​с выпуском 1.7.

Следующая версия работает правильно:

(defn dot3 
    "3d vector dot product" 
    ^double [^doubles u 
      ^doubles v] 
    (+ (* (aget u 0) (aget v 0)) 
     (* (aget u 1) (aget v 1)) 
     (* (aget u 2) (aget v 2)))) 

user=> (dot3 (double-array [4.0 5.0 6.0]) (double-array [1.0 2.0 3.0])) 
32.0 
+0

Спасибо. Это прояснилось для меня. Но я не знаю, как я мог бы понять это из ошибки компиляции ... Я бы хотел, чтобы он потерпел неудачу (или предупредил), если я сделаю что-то костяное, как использование PersistentVector вместо примитивного массива ... –

+1

Существует примитивно-математическая библиотека, которая помогает [ztellman/primative-math] (https://github.com/ztellman/primitive-math) - и да, сообщения Clojure об ошибке/компиляции часто сложны для расшифровки. – noisesmith

+0

Спасибо за этот указатель. Я определенно воспользуюсь им. –

Смежные вопросы