Fork me on GitHub
#sci
<
2021-03-04
>
denik18:03:48

Is there a way to keep ns transitions around between evaluations?

(def sci-ctx (sci/init {}))

(defn eval-form [form]
  (sci/with-bindings {sci/ns @sci/ns}
                     (sci/eval-form sci-ctx form)))

(eval-form '(do (in-ns 'foo)
                (ns-name *ns*)))
;=> foo

(eval-form '(ns-name *ns*))
;=> user ;; not foo anymore!

borkdude18:03:38

@denik with-bindings implies that the binding is restored when the body has ended. If you want to implement some kind of REPL then it's best to have the loop inside the with-bindings

denik18:03:24

@borkdude I don’t have traditional REPL but more something like REP where a client sends new forms and triggers the next evaluation cycle

denik18:03:52

I tried wrapping the eval-form function inside with-bindings but that threw errors

borkdude18:03:53

So you want to store the ns state per client?

borkdude18:03:13

Do you have multiple clients with different states?

denik18:03:29

Only one client

borkdude18:03:25

You could store the ns in some kind of atom and bind it the next time

borkdude18:03:50

(reset! the-current-ns (sci/eval-string* ctx "*ns*"))

denik18:03:14

let me try that

borkdude18:03:15

and then (sci/with-bindings {sci/ns (or @the-current-ns sci/ns)} ...)

denik19:03:49

nice, might have found a simpler solution:

(def sci-ctx (sci/init {}))

(def current-ns (atom @sci/ns))

(defn eval-form [form]
  (sci/with-bindings {sci/ns @current-ns}
                     (let [ret (sci/eval-form sci-ctx form)]
                       (reset! current-ns @sci/ns)
                       ret)))

(eval-form '(do (in-ns 'foo)
                (ns-name *ns*)))
;=> foo
(eval-form '(ns-name *ns*))
;=> foo

denik19:03:52

nice thanks for the reference