2024 年 Clojure 状况调查中分享您的想法!

欢迎!请查看关于页面以获取更多关于此如何工作的小信息。

+3
语法和读取器

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

我的初步回答得到确认,这是通过这个 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

编辑

我还不知道答案,但似乎从 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."
...