在原子上迭代文件时出现 NullPointerException
NullPointerException on iterating over a file on atom
我是 Clojure 的新手,我正在构建一个从文件中读取元组并检查第一个元素是否已经在 (atom{})
.
中的小函数
但在第一次迭代后,我在第 ((println "OK")))
行继续收到 NullPointerException
。我究竟做错了什么?这是代码:
(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)
你多了一层括号:((println "OK"))
.
(println "OK")
的结果是 nil
,因此额外的一对括号看起来像是对 nil 的函数调用:(nil)
。在 Java 中,等效代码将是 null()
,这没有任何意义。
请记住,在 Clojure 中,括号表示 "function call"。
2015-9-17 更新:
如果函数语法是:
(if <cond-expr>
<true-expr>
<false-expr> )
这 3 个表达式可以是像 5
这样的常量值,也可以是像 (+ 2 3)
这样的函数调用。整个 (if ...)
表达式的 return 值是 <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)
的结果为真,因此函数 (+ 9 10)
被求值并且该函数的结果被 return 编辑为整个 (if ...)
表达式的结果。所以,我们得到结果 19
而不是 -1
.
请记住,在 Clojure 中括号表示 "function call"。你必须从 Java 等人那里学习括号经常被用作 "grouping operator" 的想法。在 Java、
2 = (2) = ((2)) = ...
因为重复 "grouping" 一个值没有区别。在 Clojure 中,语法 (2)
表示“找到名为 2
的函数并使用零参数调用它(在 Java 中这将是 2()
,这是非法的)。
不要将 println
调用括在两组括号中。仅使用一对。括号中的内容通常被理解为函数或宏调用。 Clojure 计算内部括号中的 println
。然后 println
returns nil
,由于外括号,Clojure 尝试将其用作函数。 nil
是 Java 的 null
,这导致了异常。
我是 Clojure 的新手,我正在构建一个从文件中读取元组并检查第一个元素是否已经在 (atom{})
.
但在第一次迭代后,我在第 ((println "OK")))
行继续收到 NullPointerException
。我究竟做错了什么?这是代码:
(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)
你多了一层括号:((println "OK"))
.
(println "OK")
的结果是 nil
,因此额外的一对括号看起来像是对 nil 的函数调用:(nil)
。在 Java 中,等效代码将是 null()
,这没有任何意义。
请记住,在 Clojure 中,括号表示 "function call"。
2015-9-17 更新:
如果函数语法是:
(if <cond-expr>
<true-expr>
<false-expr> )
这 3 个表达式可以是像 5
这样的常量值,也可以是像 (+ 2 3)
这样的函数调用。整个 (if ...)
表达式的 return 值是 <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)
的结果为真,因此函数 (+ 9 10)
被求值并且该函数的结果被 return 编辑为整个 (if ...)
表达式的结果。所以,我们得到结果 19
而不是 -1
.
请记住,在 Clojure 中括号表示 "function call"。你必须从 Java 等人那里学习括号经常被用作 "grouping operator" 的想法。在 Java、
2 = (2) = ((2)) = ...
因为重复 "grouping" 一个值没有区别。在 Clojure 中,语法 (2)
表示“找到名为 2
的函数并使用零参数调用它(在 Java 中这将是 2()
,这是非法的)。
不要将 println
调用括在两组括号中。仅使用一对。括号中的内容通常被理解为函数或宏调用。 Clojure 计算内部括号中的 println
。然后 println
returns nil
,由于外括号,Clojure 尝试将其用作函数。 nil
是 Java 的 null
,这导致了异常。