Clojure: исключение NullPointerException с использованием LazySeq - PullRequest
0 голосов
/ 09 мая 2019

Я получаю исключение NullPointerException при попытке доступа к LazySeq в первый раз, line-items - что занимает некоторое время для оценки, затем оно разрывается с NullPointerException на следующей строке, вычисляя total-exc :

(defn orders->invoice [db billing-account-id dt orders resource-name]
    (let [line-items (mapcat (partial order->line-items db dt resource-name) orders) ;;lazy
          total-exc  (reduce + (map :invoice-item/total-exclusive line-items))       ;; NullPointerException
          total-inc  (reduce + (map :invoice-item/total-inclusive line-items))]

     {:invoice/items           line-items
      :invoice/total-exclusive total-exc
      :invoice/total-inclusive total-inc}))

Нет пропущенных данных, как будто я помещаю строку, где есть разрывы в блоке try catch, проглатываю его и пытаюсь сделать то же самое в блоке catch, он будет работать:

(try 
    (reduce + (map :invoice-item/total-exclusive line-items)) 
    (catch Exception e
      (clojure.pprint/pprint (.getStackTrace e))
      (reduce + (map :invoice-item/total-exclusive line-items))))

Stacktrace:

[[java.util.concurrent.FutureTask report "FutureTask.java" 122],
 [java.util.concurrent.FutureTask get "FutureTask.java" 192],
 [clojure.core$deref_future invokeStatic "core.clj" 2300],
 [clojure.core$future_call$reify__8439 deref "core.clj" 6974],
 [clojure.core$deref invokeStatic "core.clj" 2320],
 [clojure.core$deref invoke "core.clj" 2306],
 [clojure.core$map$fn__5851 invoke "core.clj" 2755],
 [clojure.lang.LazySeq sval "LazySeq.java" 42],
 [clojure.lang.LazySeq seq "LazySeq.java" 58],
 [clojure.lang.RT seq "RT.java" 531],
 [clojure.core$seq__5387 invokeStatic "core.clj" 137],
 [clojure.core$filter$fn__5878 invoke "core.clj" 2809],
 [clojure.lang.LazySeq sval "LazySeq.java" 42],
 [clojure.lang.LazySeq seq "LazySeq.java" 51],
 [clojure.lang.RT seq "RT.java" 531],
 [clojure.core$seq__5387 invokeStatic "core.clj" 137],
 [clojure.core$map$fn__5851 invoke "core.clj" 2746],
 [clojure.lang.LazySeq sval "LazySeq.java" 42],
 [clojure.lang.LazySeq seq "LazySeq.java" 51],
 [clojure.lang.RT seq "RT.java" 531],
 [clojure.core$seq__5387 invokeStatic "core.clj" 137],
 [clojure.core$concat$cat__5480$fn__5481 invoke "core.clj" 734],
 [clojure.lang.LazySeq sval "LazySeq.java" 42],
 [clojure.lang.LazySeq seq "LazySeq.java" 58],
 [clojure.lang.RT seq "RT.java" 531],
 [clojure.core$seq__5387 invokeStatic "core.clj" 137],
 [clojure.core$map$fn__5851 invoke "core.clj" 2746],
 [clojure.lang.LazySeq sval "LazySeq.java" 42],
 [clojure.lang.LazySeq seq "LazySeq.java" 51],
 [clojure.lang.Cons next "Cons.java" 39],
 [clojure.lang.RT next "RT.java" 709],
 [clojure.core$next__5371 invokeStatic "core.clj" 64],
 [clojure.core.protocols$fn__8144 invokeStatic "protocols.clj" 169],
 [clojure.core.protocols$fn__8144 invoke "protocols.clj" 124],
 [clojure.core.protocols$fn__8099$G__8094__8108 invoke "protocols.clj" 19],
 [clojure.core.protocols$seq_reduce invokeStatic "protocols.clj" 27],
 [clojure.core.protocols$fn__8131 invokeStatic "protocols.clj" 75],
 [clojure.core.protocols$fn__8131 invoke "protocols.clj" 75],
 [clojure.core.protocols$fn__8073$G__8068__8086 invoke "protocols.clj" 13],
 [clojure.core$reduce invokeStatic "core.clj" 6824],
 [clojure.core$reduce invoke "core.clj" 6810],
 [user$eval106182 invokeStatic "form-init3664079349963806059.clj" 15],
 [user$eval106182 invoke "form-init3664079349963806059.clj" 14],
 [clojure.lang.Compiler eval "Compiler.java" 7176],
 [clojure.lang.Compiler eval "Compiler.java" 7131],
 [clojure.core$eval invokeStatic "core.clj" 3214],
 [clojure.core$eval invoke "core.clj" 3210],
 [clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414],
 [clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414],
 [clojure.main$repl$fn__9077 invoke "main.clj" 435],
 [clojure.main$repl invokeStatic "main.clj" 435],
 [clojure.main$repl doInvoke "main.clj" 345],
 [clojure.lang.RestFn applyTo "RestFn.java" 137],
 [clojure.core$apply invokeStatic "core.clj" 665],
 [clojure.core$apply invoke "core.clj" 660],
 [refactor_nrepl.ns.slam.hound.regrow$wrap_clojure_repl$fn__62865 doInvoke "regrow.clj" 18],
 [clojure.lang.RestFn invoke "RestFn.java" 1523],
 [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__53116 invoke "interruptible_eval.clj" 87],
 [clojure.lang.AFn applyToHelper "AFn.java" 152],
 [clojure.lang.AFn applyTo "AFn.java" 144],
 [clojure.core$apply invokeStatic "core.clj" 665],
 [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973],
 [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973],
 [clojure.lang.RestFn invoke "RestFn.java" 425],
 [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 85],
 [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 55][clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__53161$fn__53164 invoke "interruptible_eval.clj" 222],
 [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__53156 invoke "interruptible_eval.clj" 190],
 [clojure.lang.AFn run "AFn.java" 22],
 [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1149],
 [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 624],
 [java.lang.Thread run "Thread.java" 748]]

Возвращаемое значение:

176805

Это имеетработали годами, с той лишь разницей, что для обработки этих данных требуется гораздо больше данных.

Я пытался реализовать LazySeq с помощью doall - то же самое, но только в первый раз.

Я никогда не видел такого поведения раньше, поэтому любая помощь очень ценится.

1 Ответ

1 голос
/ 09 мая 2019

У вашего line-items есть исключение, которое не появляется, пока вы не попытаетесь реализовать его для суммирования. Вы увидите то же поведение от значения, подобного этому:

user=> (def xs (take 10 (map #(/ 2 %) (iterate dec 3))))
#'user/xs
user=> (apply + xs)
Execution error (ArithmeticException) at user/fn (REPL:1).
Divide by zero
user=> (apply + xs)
11/3 ;; (which is 2/3 + 2/2 + 2/1)

Тот факт, что вы получите правильный результат со второй попытки, не означает, что ваш ввод был действительным. Исключение только что заставило xs выбросить все вещи после последнего действительного элемента.

Итак, вместо того, чтобы искать ошибку в опубликованном вами коде, выясните, как в итоге вы получили недопустимый line-items.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...