sci 2023-11-02

Does Sci have something builtin to make certain vars available in every namespace? For example, when I expose vars via {:bindings ...} they are not available in namespaces that I load via :load-fn

no it doesn't but you could choose to evaluate something with :refer before you evaluate anything else

Ok yeah maybe I need to think about it a bit differently. Thanks for the quick feedback!

👍 1

Maybe I found a bug with macros and refers:

(let [ctx  {:load-fn (fn [_] {:file "other.clj"
                              :source " (ns other
                                          (:require [mylib.core :refer :all]))
                                          (defn hello-fn [& body]
                                            (hello (apply str body)))

                                          (defmacro hello-macro [& body]
                                            `(hello (str ~@body)))"})
            :namespaces {'mylib.core {'hello (fn [s] (str "hello " s))}}}]
  ;; This is ok
  (sci/eval-string (str '(do (require '[other :refer :all])
                             (hello-fn
                              "jeroen")))
                   ctx)

  ;; This is not ok, tries to resolve hello as `other/hello and not mylib.core/hello
  (sci/eval-string (str '(do (require '[other :refer :all])
                             (hello-macro
                              "jeroen")))
                   ctx))

ah so it's a bug with syntax quote / resolve then I guess

please file an issue

👍 1

to work around it, write the namespace name fully in the macro

👍 1

hmm, this does work in SCI:

user=> (sci/eval-string "(require '[clojure.set :refer :all]) `(intersection)")
(clojure.set/intersection)
user=> (sci/eval-string "#_(require '[clojure.set :refer :all]) `(intersection)")
(user/intersection)

I wonder if you're able to make a repro that is similarly small?

or can you try those examples?

could also be related to your namespace not being proper vars, let me test that

yeah these examples work. I'll try it in my macro

that seems to be it: non-var:

user=> (sci/eval-string "(require '[my.namespace :refer :all]) `(intersection)" {:namespaces {'my.namespace {'intersection (fn [])}}})
(user/intersection)

Ah ok, so I should add the {:obj ns-var} to my namespaces. I didn't do that yet 😅

ah:

user=> (sci/eval-string "(require '[my.namespace :refer :all]) `(intersection)" {:namespaces {'my.namespace {'intersection (sci/new-var 'intersection (fn []) {:ns (sci/create-ns 'my.namespace)})}}})
(my.namespace/intersection)

well, maybe I can fix it without you having to do that

I'll look into it

🙌 1

I didn't know what it was for yet, I'm ok adding it

well maybe I can simplify this

yeah it's not so easy to fix without changing a lot of stuff, so perhaps it's better to create a SCI var. If you are coping an existing var you can use (sci/copy-var my-function my-sci-ns)

where my-sci-ns is created with (sci/create-ns 'my-sci-ns)

Ok I have it working now with your suggestion. Will need to clean it up a bit and understand how copy-var works exactly. Thanks for your help!

👍 1