【问题标题】:Why does this anonymous function starting with println result in a NullPointerException?为什么这个以 println 开头的匿名函数会导致 NullPointerException?
【发布时间】:2012-09-21 16:18:46
【问题描述】:

我正在学习pmap并编写了以下函数:

(pmap #((println "hello from " (-> (Thread/currentThread) .getName)) 
         (+ %1 %2)) 
   [1 1 1] [-1 -1 -1])

运行时,结果为NullPointerException

(hello from  clojure-agent-send-off-pool-4
hello from  clojure-agent-send-off-pool-3
hello from  clojure-agent-send-off-pool-5
NullPointerException   user/eval55/fn--56 (NO_SOURCE_FILE:11)

为什么会这样?我已经理解并观察到fn 的主体是隐含的do

【问题讨论】:

    标签: clojure


    【解决方案1】:

    匿名fn 文字#() 没有隐式do

    【讨论】:

    • 我看到(使用macroexpand#() 扩展为fn* 而不是fn(宏)。
    • 所以你会用 fn[x] 替换 #() 吗?
    • 使用(fn [] (println ) ...)#((do (println ...)
    • fn* vs fn 在这里不相关。不同之处在于#((x %)) 扩展为(fn [%] ((x %))),而不是(fn [%] (x %))
    • 不知道你为什么认为“不相关” - 只是一个观察。见stackoverflow.com/questions/12488479/…另外,我有一个错误:它应该是#(do (println ...
    【解决方案2】:

    您在 2 个括号中有 println,因此评估了 println 的结果。 println 总是返回 nil,因此返回 NullPointerException。

    尝试从#() 中删除多余的括号:

       (pmap #(println "hello from " 
             (-> (Thread/currentThread) .getName) 
             (+ %1 %2)) 
              [1 1 1] [-1 -1 -1] )
    

    编辑:

    那么您将需要 do,如其​​他 cmets 中所述:

    (pmap #(do (println "hello from " 
         (-> (Thread/currentThread) .getName)) 
         (+ %1 %2)) 
          [1 1 1] [-1 -1 -1] )
    

    do#() 读取器宏中之所以需要,原因并不是函数不包含隐式do,而是与宏的扩展方式有关。基本上,该宏采用单一形式,因此需要显式的do

    【讨论】:

    • 它扩展为:(fn* [p1__13# p2__14#] (println "hello from " (-> (Thread/currentThread) .getName) (+ p1__13# p2__14#)))。但是,现在您已经破坏了我的 pmap 函数的意图。查看返回值。
    • 你希望结果是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多