我是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)
答案 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
,导致异常。