nrepl / nrepl

A Clojure network REPL that provides a server and client, along with some common APIs of use to IDEs and other tools that may need to evaluate Clojure code in remote environments.
https://nrepl.org
775 stars 96 forks source link

Can't define dynamic var in nrepl #271

Closed opqdonut closed 1 month ago

opqdonut commented 2 years ago

Expected behavior

% clj
Clojure 1.10.3
user=> (def ^:dynamic *dyn* 1)
#'user/*dyn*
user=> (binding [*dyn* 2] (prn *dyn*))
2

Actual behavior

% clj -Sdeps '{:deps {nrepl/nrepl {:mvn/version "0.9.0"}}}' -M -m nrepl.cmdline --interactive
nREPL server started on port 41271 on host localhost - nrepl://localhost:41271
nREPL 0.9.0
Clojure 1.10.3
OpenJDK 64-Bit Server VM 17-ea+19-Debian-1
Interrupt: Control+C
Exit:      Control+D or (exit) or (quit)
user=> (def ^:dynamic *dyn* 1)
Warning: *dyn* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *dyn* or change the name. (NO_SOURCE_PATH:1)
#'user/*dyn*
user=> (binding [*dyn* 2] (prn *dyn*))
Execution error (IllegalStateException) at user/eval2146 (REPL:1).
Can't dynamically bind non-dynamic var: user/*dyn*

Steps to reproduce the problem

See above.

Environment & Version information

Clojure version

1.10.3

Java version

17

Operating system

Debian Linux

bbatsov commented 2 years ago

Seems to be an issue with the built-in CLI, as I couldn't reproduce this when using CIDER or lein repl (which in turn uses REPLy).

hukka commented 2 years ago

I can also reproduce it using Conjure, which uses nrepl: https://github.com/hukka/repl-driven-bug-repro

alexander-yakushev commented 3 months ago

I'm pretty sure this happens because of this: https://github.com/nrepl/nrepl/blob/master/src/clojure/nrepl/cmdline.clj#L111-L114

The --interactive REPL reads the input form with read and then prints it back with pr-str which doesn't print metadata by default. While it is possible to amend this with *print-meta* flag, I think that ideally the REPL should read the input as a string and pass that further as-is. Smaller chance to run into similar issues in the future.

bbatsov commented 3 months ago

Good catch!