Hi!
@sakalli and I are creating a small middleware that listens to evaluation of code and keeps track of evaluation results. (This is part of an upcoming version of the Notespace project.)
With :op "eval"
, this seems to work nicely.
However, we are also interested in :op "load-file"
, since that is the kind of request when one evaluates a whole buffer in CIDER.
Then, the nREPL response only tells about the evaluation result of the last top-level form.
This kind of op directly calls clojure.lang.Compiler/load
:
https://github.com/clojure/tools.nrepl/blob/2263b6b/src/main/clojure/clojure/tools/nrepl/middleware/load_file.clj#L62
So, it seems that on whole-buffer evaluation, we will not be able to get the return values of intermediate top-level forms, but only of the last one.
Any ideas about how to overcome that?
There's no way to circumvent this with load-file
.
If you need to eval all top-level forms you'll need to walk over them and run eval
for each. That won't be a problem if you eval in a single session as the evaluations will be serialized.
Thanks for the quick help, @bozhidar!
We tried to evaluate a region with a few top-level forms (through :op "eval"
), and it actually sent us multiple responses with all evaluation values.
Is it surprising?
Request (removed the bit :session
member, so that it prints nicely):
{:transport
#object[nrepl.middleware.caught$caught_transport$reify__915 0x5e5191a5 "nrepl.middleware.caught$caught_transport$reify__915@5e5191a5"],
:ns "notespace.nrepl",
:nrepl.middleware.print/print-fn
#function[nrepl.middleware.print/wrap-print/fn--891/print--893],
:file "/home/daslu/dev/scicloj/notespace/src/notespace/nrepl.clj",
:load-tests? "true",
:nrepl.middleware.print/quota 1048576,
:nrepl.middleware.print/print "cider.nrepl.pprint/pr",
:op "eval",
:column 1,
:line 50,
:nrepl.middleware.caught/caught-fn
#function[clojure.main/repl-caught],
:id "132",
:code "(+ 1 2)\n\n(+ 3 4)\n\n",
:nrepl.middleware.print/stream? []}
Response messages:
{:id "132",
:session "736cc68a-a5fe-44d5-8906-0ba56ca15dda",
:ns "notespace.nrepl",
:value 3,
:nrepl.middleware.print/keys #{:value}}
{:id "132",
:session "736cc68a-a5fe-44d5-8906-0ba56ca15dda",
:ns "notespace.nrepl",
:value 7,
:nrepl.middleware.print/keys #{:value}}
{:id "132",
:session "736cc68a-a5fe-44d5-8906-0ba56ca15dda",
:status #{:done}}
If it seems interesting, I can share a self-contained example tomorrow. Anyway, your comment already helped wonderfully. 🙏
<https://ask.clojure.org/index.php/10624/should-load-file-use-the-repls-eval-function>
that is expected to me. evaluating a region can (and here does) have multiple effects
load-file is a primitive offered by the clojure compiler
Thanks, @dpsutton!
I don’t understand the answer…
Also, eval a region and get back results for each top level form in it surprises me. I would expect the reader to get the text, eval each form and give me back the result of the last thing evaled.
that's just not what (def x 1)(def y 2) (def z 3)
would ever do, and that's all evaling a region does, just send a region over to the repl
/tmp ❯❯❯ clj
Clojure 1.10.3
user=> (def x 1)(def y 2)(def z 3)
#'user/x
#'user/y
#'user/z
user=>
I’m now realizing that Calva does not have a working eval region command.
it's probably quite infrequently used. i'd wait for a feature request to be honest
Well, the command is actually named Evaluate current form (or selection) so we are breaking the promise…
Noone has complained so far, and it must have been broken for quite a while. So you are probably right about infrequent.