Clojure 2024 状态调查 中分享你的看法!

欢迎!请查阅关于页面获取更多关于这如何工作的信息。

+3
<\/a><\/span> 语法和读取器

Clojure 1.10.1 user=> #=(println 1) 1 1 nil user=> (read-string "#=(println 1)") 1 nil

在 Clojure 1.8.0 中 1 只打印一次。

我正在 Ubuntu 系统上使用 clj 工具,并使用 Clojure 1.10.1。

2 个回答

+2
<\/a><\/span>

我之前答案的教育性猜测被这次 REPL 会话证实了。

$ clj
Clojure 1.10.1

;; Confirm the new behavior of clojure.main/repl-read reading input twice
user=> #=(println 1)
1
1
nil

;; define a function that behaves like old clojure.main/repl-read

(defn old-repl-read
  [request-prompt request-exit]
  (or ({:line-start request-prompt :stream-end request-exit}
       (clojure.main/skip-whitespace *in*))
      (let [input (clojure.core/read {:read-cond :allow} *in*)]
        (clojure.main/skip-if-eol *in*)
        input)))
#'user/old-repl-read

;; Start a nested REPL using old-repl-read
user=> (clojure.main/repl :read old-repl-read)

;; Confirm the old behavior of reading input once
user=> #=(println 1)
1
nil

;; Press Ctrl-D to exit inner REPL, returning to original REPL
user=> nil

;; Confirm back to new behavior of reading twice
user=> #=(println 1)
1
1
nil
+1
<\/a><\/span>
编辑

我还没有找到答案,但从 Clojure 版本 1.10.0-RC2 开始,似乎出现了行为上的差异。

$ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.0-RC1"}}}'
Clojure 1.10.0-RC1
user=> #=(println 1)
1
nil
user=> ^D

$ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.0-RC2"}}}'
Clojure 1.10.0-RC2
user=> #=(println 1)
1
1
nil

进一步的调查表明,新行为首次出现在以下提交中:https://github.com/clojure/clojure/commit/817abb3d0ca3b7ee80cfe17b5cfe3ea8306f0720

猜测:该提交包括了一个新的用作 Clojure 默认 REPL 的 renumbering-read 函数,如果在第一次读取成功后,它将再次读取。

(defn renumbering-read
  "Reads from reader, which must be a LineNumberingPushbackReader, while capturing
  the read string. If the read is successful, reset the line number and re-read.
  The line number on re-read is the passed line-number unless :line or
  :clojure.core/eval-file meta are explicitly set on the read value."
...