sci

2022-04-29T09:10:16.862269Z

So I apologize - I didn't mean to privately message you before about how to manage namespaces when coding a repl using sci - you very kindly replied with the following code:

(def !last-ns (volatile! @sci/ns))

(defn eval-string [s]
  (sci/binding [sci/ns @!last-ns]
    (let [rdr (sci/reader s)]
      (loop [res nil]
        (let [form (sci/parse-next @!ctx rdr)]
          (if (= :sci.core/eof form)
            (do
              (vreset! !last-ns @sci/ns)
              res)
            (recur (sci/eval-form @!ctx form))))))))

2022-04-29T09:10:41.739519Z

I'm not using that code quite yet, but if I try something like (ns client) in my repl, I get the following error, and I'm curious what's causing it:

2022-04-29T09:11:07.046819Z

Can't change/establish root binding of #'clojure.core/*ns* with set

2022-04-29T09:11:36.961069Z

Maybe if I used the code you showed, that somehow wouldn't happen but if that's the case, I'm confused.

borkdude 2022-04-29T09:13:41.020879Z

@pmooser The problem is that (ns client) will change the value of the dynamic var *ns* but it may only be changed inside a binding. eval-string and eval-string* do that automatically, but eval-form does not

borkdude 2022-04-29T09:14:32.063469Z

With "do that automatically" I mean: they surround the evalution with a binding

2022-04-29T09:14:35.188299Z

So is it sufficient for me just to bind (using sci/binding ) ... sci/ns ?

👍 1
borkdude 2022-04-29T09:14:45.250919Z

which also means that the value of *ns* is restored after the binding

borkdude 2022-04-29T09:14:48.847999Z

yes

2022-04-29T09:14:50.419929Z

Or do I need to use "normal" (cljs) binding of *ns* ?

2022-04-29T09:14:51.483689Z

ok

2022-04-29T09:17:04.891589Z

Ok great - that does indeed fix it. Now I'll integrate the rest of what you gave me. Thanks - I have things almost perfectly working I think ...

2022-04-29T10:59:16.852509Z

@borkdude In cljs, what's the practical difference between using a volatile vs. storing a value in an atom ?

2022-04-29T10:59:21.010029Z

(in this context, I mean)

borkdude 2022-04-29T11:30:41.870669Z

@pmooser volatile is a light weight atom with less features and therefore a bit more performant

2022-04-29T14:19:45.068449Z

Sure, but given that performance in a repl (between entered data) is sort of gated by typing speed, it seems like that difference isn't materially important here. In any case, it sounds like it isn't required, but I appreciate the additional info!

Kirill Chernyshov 2022-04-29T11:41:40.501169Z

"less features" means not thread safe and should be used only in isolation.

borkdude 2022-04-29T11:46:01.170769Z

yes, but we're talking CLJS here so threads are not a concern

Kirill Chernyshov 2022-04-29T11:52:56.494899Z

oops, sorry ) too many channels )

borkdude 2022-04-29T11:53:25.274409Z

With "here" I mean in the context of @pmooser’s question, not this channel > In cljs, what's the practical difference

2022-04-29T14:25:35.469159Z

Given a sci context, is there a way to say "what is the sci namespace for symbol x " ?

2022-04-29T14:26:01.200579Z

(outside of sci itself ... I'm trying to put bindings together for the very first call to the sci evaluator ... once I've been through there, it's not really a problem)

2022-04-29T14:26:15.700549Z

I suppose I could eval something and get sci to return the namespace, but it seems like there must be a better way.

borkdude 2022-04-29T14:28:02.478159Z

@pmooser There currently isn't a better way than eval-ing something :) But I guess we could expose (sci/find-ns ctx sym)?

borkdude 2022-04-29T14:28:12.550359Z

I've needed that myself too. I could do that right now

2022-04-29T14:29:59.717559Z

I suppose I shouldn't be afraid of eval-ing something - I just have written my own interface (since my use of sci is an adaptation of something I used to have) and I have a symbol in hand which corresponds to the namespace I want, but the actual place the namespace gets created is "somewhere else" (where I'm creating namespaces and copying existing cljs namespaces), so what I have easy access to is simply the ctx ...

2022-04-29T14:30:26.271619Z

I also don't know enough about the sci representation of namespaces to do anything other than call "eval" safely, since I don't know exactly how they evolve over time.

borkdude 2022-04-29T14:31:38.368949Z

indeed, the representation inside the context is subject to change, but the outer API should remain stable

borkdude 2022-04-29T14:31:49.978629Z

but is find-ns something you were looking for?

borkdude 2022-04-29T14:32:01.313069Z

(find-ns ... ...) -> SCI ns object?

2022-04-29T14:32:09.781959Z

Yes, that would work perfectly in my case!

borkdude 2022-04-29T14:32:28.175539Z

good, just a minute then

2022-04-29T14:36:05.428379Z

Do you think it's sufficiently "safe" (from an API stability point of view) to do something like: (keys (:namespaces @(:env sci-ctx))) to find the list of namespace (symbols) that sci knows about?

2022-04-29T14:36:21.294919Z

(or is there a better way to enumerate namespaces)

2022-04-29T14:36:31.131569Z

This isn't a vital feature, but I was curious.

borkdude 2022-04-29T14:37:11.542639Z

@pmooser

b2e1354c7a24ce22d5f5b8a901d3c39cd0c8baf3

borkdude 2022-04-29T14:37:51.637839Z

@pmooser There is a better way, which is to evaluate (all-ns) - I could also expose that one, just a moment

2022-04-29T14:41:18.001149Z

It's really nice to be able to enumerate namespaces on the cljs side.

borkdude 2022-04-29T14:44:10.342859Z

@pmooser Something like this?

user=> (require '[sci.core :as sci])
nil
user=> (def ctx (sci/init {}))
#'user/ctx
user=> (def all-nss (sci/all-ns ctx))
#'user/all-nss
user=> (map sci/ns-name all-nss)
(user clojure.core clojure.set clojure.edn clojure.repl clojure.string clojure.walk clojure.template)

2022-04-29T14:45:34.349439Z

Yup, I think that would work great for my purposes.

borkdude 2022-04-29T14:46:17.714219Z

fcf7e6067f091fd2cf2843660349e820c4449dd8

2022-04-29T14:47:20.228909Z

Thank you ... trying some of this out (it may take me a little bit)

2022-04-29T14:59:59.043379Z

Ok, I imagine I'm doing something wrong. So I create my namespaces and I have my context. Then I pull out a specific namespace (based on a config file), which in this case is user: (sci/find-ns sci-ctx (:default-ns repl-config)) That returns the right ns, which has the right name. However, when I call sci to evaluate something, I set up bindings like this:

(sci/binding [sci/ns (:current-ns @state)] ...)
And when I call eval, after I do the eval, if I ask sci/ns for its name, I get *ns*

2022-04-29T15:01:06.756969Z

Let me see what it says inside binding but before eval

2022-04-29T15:02:00.816449Z

So that happens even before I call eval.

borkdude 2022-04-29T15:02:10.176069Z

Please be more precise, make a code example

2022-04-29T15:02:15.152379Z

Yes, one moment.

2022-04-29T15:10:00.510859Z

(let [ns (sci/find-ns (:sci-env @state) 'user)]
  ;; prints "user"
  (println "1: name ns" (sci/ns-name ns))
  (sci/binding [sci/ns ns]
    ;; prints "*ns*"
    (println "2: name ns" (sci/ns-name sci/ns))))

borkdude 2022-04-29T15:11:47.762659Z

The result of (sci/ns-name ns) prints *ns* ?

2022-04-29T15:12:20.622059Z

The result of sci/ns-name (as shown in the code snippet you requested) is "user".

borkdude 2022-04-29T15:13:15.076069Z

I don't get to which part "`;; prints "ns""` refers to

2022-04-29T15:13:16.211659Z

(sci/ns-name ns) --> "user" (sci/ns-name sci/ns) --> *ns*

2022-04-29T15:13:20.867939Z

the following println

2022-04-29T15:13:32.593589Z

Each comment above the println that says "prints" says what the print does

borkdude 2022-04-29T15:13:38.716049Z

yes, this is expected. sci/ns is a SCI var. you should first deref it

2022-04-29T15:13:49.524609Z

oof

2022-04-29T15:14:25.988779Z

Yes, I see you do that in your code example you kindly provided. It just went over my head.

2022-04-29T15:14:34.299359Z

Sorry and thank you.

borkdude 2022-04-29T15:14:51.155779Z

No problemo

2022-04-29T15:10:34.613349Z

Make sense?

2022-04-29T15:18:48.838909Z

@borkdude Ok, I can confirm both changes are working for me (all-ns and find-ns).

👍 1