Welcome! Please see the About page for a little more info on how this works.

+3 votes
in Syntax and reader by

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

On Clojure 1.8.0 1 only prints once.

I'm on Ubuntu using the clj tool and Clojure 1.10.1.

2 Answers

+2 votes
by

Educated guess of my earlier answer confirmed, with this REPL session:

$ 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 vote
by
edited by

I do not know the answer yet, but there appears to be a difference in behavior starting with Clojure version 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

And a little more investigation shows that the new behavior first occurred with this commit: https://github.com/clojure/clojure/commit/817abb3d0ca3b7ee80cfe17b5cfe3ea8306f0720

Educated guess: That commit includes a new renumbering-read function used by Clojure's default REPL, which reads a second time if the first read is successful.

(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."
...