【问题标题】:Why is source-fn failing to find source code in this specific circumstance?为什么 source-fn 在这种特定情况下找不到源代码?
【发布时间】:2017-06-09 21:00:04
【问题描述】:

这种情况很难重现。首先我创建一个 clj 文件,其中包含:

(ns myns)

(defn myfn [x] x)

然后我创建第二个 clj 文件,其中包含:

(ns myns2
 (:require [myns :as m]
           [clojure.repl :as repl]))

(comment

 (second (iterate repl/source-fn 'm/myfn))

 (take 2 (iterate repl/source-fn 'm/myfn))

)

然后我启动一个 REPL 并在其中加载第二个文件。最后,我通过将两个 cmets 发送到 REPL 来评估它们。第一个表达式将按预期产生"(defn myfn [x] x)"。然而,第二个表达式产生'(m/myfn nil)。这是怎么回事?

请注意,将 'm/myfn 完全限定为 'myns/myfn 会恢复匹配行为。我也知道迭代 source-fn 有点古怪,但这是我所知道的重现行为的最简单方法。

【问题讨论】:

  • 两种情况之间的一个区别:secondsource-fn 在 REPL 的 eval 步骤中运行; take 2, source-fn 在打印步骤中运行(由于懒惰)。

标签: reflection clojure namespaces


【解决方案1】:

我不明白你的结果。通过lein test 从文件运行,我得到不同的结果:

(newline)
(def iii (iterate inc 0))
(spyx (nth iii 0))
(spyx (nth iii 1))
(spyx (nth iii 2))

(defn foo [x] 42)
(def bar (repl/source-fn 'foo))
(newline)
(spyx bar)

(newline)
(spyx  (take 1 (iterate repl/source-fn 'foo)))
(spyx  (take 2 (iterate repl/source-fn 'foo)))

(newline)
(spyx  (first  (iterate repl/source-fn 'foo)))
(spyx  (second (iterate repl/source-fn 'foo)))

结果:

(nth iii 0) => 0
(nth iii 1) => 1
(nth iii 2) => 2

bar => "(defn foo [x] 42)"

(take 1 (iterate repl/source-fn (quote foo))) => (foo)
(take 2 (iterate repl/source-fn (quote foo))) => (foo "(defn foo [x] 42)")

(first (iterate repl/source-fn (quote foo))) => foo
(second (iterate repl/source-fn (quote foo))) => "(defn foo [x] 42)"

【讨论】:

  • 您无法复制,因为您使用的是 spyx。如 cmets 中所述,不同之处在于 iterate 返回一个惰性序列,该序列仅在评估完成后打印。 spyx 通过在 eval 阶段将其转换为字符串来改变它。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 2020-03-13
  • 2016-03-24
  • 2021-09-22
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多