This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-20
Channels
- # announcements (30)
- # babashka (118)
- # beginners (23)
- # calva (68)
- # cljdoc (10)
- # clojars (13)
- # clojure (90)
- # clojure-bangladesh (1)
- # clojure-europe (27)
- # clojure-gamedev (1)
- # clojure-nl (11)
- # clojure-uk (4)
- # clojurescript (59)
- # community-development (3)
- # cursive (13)
- # datomic (39)
- # defnpodcast (1)
- # emacs (10)
- # figwheel-main (1)
- # fulcro (18)
- # graalvm (21)
- # honeysql (1)
- # introduce-yourself (1)
- # juxt (1)
- # lsp (197)
- # malli (19)
- # off-topic (28)
- # practicalli (2)
- # re-frame (42)
- # reagent (4)
- # reitit (7)
- # releases (2)
- # sci (35)
- # shadow-cljs (13)
- # spacemacs (4)
- # vim (3)
Heya, is there an easy way to treat namespaces loaded into the context via something like this https://github.com/babashka/sci#copy-a-namespace like source code eval’d into the compiler so that it’s getting the sci versions of the clojure.core namespace etc?
in the docs this function is provided as an example for how to load all of the functions in a library’s namespace
(reduce (fn [ns-map [var-name var]]
(let [m (meta var)
no-doc (:no-doc m)
doc (:doc m)
arglists (:arglists m)]
(if no-doc ns-map
(assoc ns-map var-name
(sci/new-var (symbol var-name) @var
(cond-> {:ns fns
:name (:name m)}
(:macro m) (assoc :macro true)
doc (assoc :doc doc)
arglists (assoc :arglists arglists)))))))
{}
(ns-publics 'foobar))
Which creates a SciVar wrapper around the function, but when the function runs it’s not ‘inside’ the context of the sci compiler e.g. if the library code calls resolve
it will be clojure.core/resolve
and not the SCI version of it. But if I slurp that namespace and eval it with sci, everything works as intended. So I’m trying to work out if there is a way to rebind everything inside a namespace with these https://github.com/babashka/sci/blob/master/src/sci/impl/namespaces.cljc#L808 at the time I’m creating the SciVar around the value.@haywood Perhaps this helps?
user=> (def ctx (sci/init {:namespaces {'user {'x 1 'foo patched-foo 'bar (fn [x] :bar)}}}))
#'user/ctx
user=> (def sci-resolve (sci/eval-string* ctx "resolve"))
#'user/sci-resolve
user=> (sci-resolve 'x)
1
user=> (defn patched-foo [x] ((sci-resolve 'bar) x))
#'user/patched-foo
user=> (def ctx (sci/merge-opts ctx {:namespaces {'user {'patched-foo patched-foo}}}))
#'ctx
user=> (sci/eval-string* ctx "(foo 1)")
:bar
You can patch your resolve
using functions to use SCI's resolve from the context.yea definitely, that or wrap the eval-string* call with (with-redefs [resolve (sci/eval-form ctx 'resolve)] (sci/eval-string* ctx code-str))
would you like to give SCI access to your entire host, or just the opposite and prevent that?
as in, do you want to give access to Clojure's resolve
or would you like to prevent this at all costs.
ah, so not even a matter of prevention, but I want resolve to know about namespaces that were previously created via sci/eval-string*
or read the file’s source in as a string and eval it that way, not sure which approach is better
you could rewrite that function, if that is within reason, to do the right thing based on some dynamic var or so
(def ^:dynamic *resolver* clojure.core/resolve)
(binding [*resolver* sci-resolve] ...)
do I have the correct mental model that when sci calls a SciVar’s wrapped function, the execution is basically external and can do whatever?
SCI just executes the provided function in the context and the behavior of that function doesn't change regardless of called within or outside of SCI
so if that function calls an HTTP service or launches a rocket, or resolves a clojure var, it doesn't matter
cool, for too long I was thinking it had the same restraints as code that was eval’d using sci
in some cases it might indeed be easier to just evaluate that function's source with eval-string* indeed
user=> (clojure.repl/source-fn 'inc)
"(defn inc\n \"Returns a number one greater than num. Does not auto-promote\n longs, will throw on overflow. See also: inc'\"\n {:inline (fn [x] `(. clojure.lang.Numbers (~(if *unchecked-math* 'unchecked_inc 'inc) ~x)))\n :added \"1.2\"}\n [x] (. clojure.lang.Numbers (inc x)))"
how come this is commented out? https://github.com/babashka/sci/blob/master/src/sci/impl/namespaces.cljc#L1453 definitely generally usable vs a naive
(-> (ns-publics 'my-lib)
vals
first
meta
:file
slurp)
$ clj
Clojure 1.11.0-alpha3
user=> (require '[sci.core :as sci])
nil
user=> (def constantly-source (clojure.repl/source-fn 'constantly))
#'user/constantly-source
user=> (def ctx (sci/init {}))
#'user/ctx
user=> (sci/eval-string* ctx (str "(in-ns 'foo) " constantly-source))
#'foo/constantly
user=> (sci/eval-string* ctx "((foo/constantly 1))")
1