2024年Clojure调查! 中分享你的想法。

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

+3
语法和Reader

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
by

我的先前回答的猜测经此 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
by
编辑 by

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