迭代原子上的文件时出现NullPointerException

时间:2015-09-16 04:42:51

标签: clojure nullpointerexception atomicity

我是Clojure的新手,我正在构建一个从文件中读取元组的小函数,并检查第一个元素是否已经在(atom{})中。

但是我在第一次迭代后继续在NullPointerException行接收((println "OK")))。我究竟做错了什么?这是代码:

(defn graph-from-file
  "Expects a string with the path for a file with a list of edges, one in each line,
And builds a graph data structure from these"
  [filepath]
  (def gr (atom{}))
  (with-open [rdr (reader filepath)]
    (doseq [line (line-seq rdr)]
      (let [[src dst] (str/split line #" ")
            ks (keyword src)]           ;define ks as the keyword
        (println (str "src: " src " dst: " dst " kw: " ks))
        (if (contains? @gr ks)
          ((println "WHAT?"))
          ((println "OK")))
        )))
  )

请注意,代码很简单,输出(WHAT?和" OK")仅用于演示目的。

以下是我得到的输出:

src: 64 dst: 48 kw: :64
OK
NullPointerException   ****/graph-from-file (core.clj:19)

2 个答案:

答案 0 :(得分:3)

您还有一层额外的括号:((println "OK"))

(println "OK")的结果是nil,因此额外的一对括号看起来像是对nil的函数调用:(nil)。在Java中,对等代码将是null(),这没有任何意义。

请记住,在Clojure中,括号表示"函数调用"。

更新2015-9-17:

如果函数语法是:

(if <cond-expr>
  <true-expr>
  <false-expr> )

3个表达式可以是5之类的常量值,也可以是(+ 2 3)之类的函数调用。整个(if ...)表达式的返回值是<true-expr><false-expr>的结果。所以我们得到:

(if true
  :wahoo
  "no such luck" ))
;=> :wahoo

(if (< (+ 2 3) 9)
  (str "Two plus three is " (+ 2 3))
  :not-likely ))
;=> Two plus three is 5

更新2015-11-1

语法如下:

(if test-value
  result-value-if-true
  result-value-if-false)

第一个例子导致:wahoo,所有三个值都是文字(即常量)。在Clojure中,任何值都可以用表达式替换:

(if (< 2 3)
  (+ 9 10)
  (- 9 10))
;=> 19

上面示例中的每个值都已被函数调用替换。 (< 2 3)的结果为true,因此将评估函数(+ 9 10),并返回该函数的结果作为整个(if ...)表达式的结果。因此,我们得到结果19而不是-1

请记住,在Clojure中,括号表示&#34;函数调用&#34;。你必须从Java等人那里学习这个想法,即括号通常被用作&#34;分组运算符&#34;。在Java中,

2 = (2) = ((2)) = ...

因为反复&#34;分组&#34;一个值没有区别。在Clojure中,语法(2)表示&#34;找到名为2的函数并使用零参数调用它(在Java中这将是2()这是非法的。)

答案 1 :(得分:2)

不要将println个调用包装在两组括号中。仅使用一对。括号中的内容通常被读作函数或宏调用。 Clojure评估内部parens中的println。然后println返回nil,并且Clojure尝试将其用作函数,因为外部的parens。 nil是Java null,导致异常。