This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-06-05
Channels
- # announcements (11)
- # architecture (22)
- # babashka (33)
- # beginners (15)
- # biff (8)
- # calva (7)
- # clj-otel (1)
- # cljs-dev (3)
- # cljsrn (5)
- # clojure (76)
- # clojure-art (1)
- # clojure-europe (36)
- # clojure-hamburg (3)
- # clojure-nl (1)
- # clojure-norway (7)
- # clojure-poland (12)
- # clojure-spec (2)
- # clojure-uk (7)
- # clojurescript (9)
- # cursive (22)
- # data-science (6)
- # datomic (7)
- # fulcro (9)
- # hoplon (14)
- # instaparse (2)
- # jobs-discuss (14)
- # london-clojurians (1)
- # matrix (32)
- # music (1)
- # nbb (8)
- # off-topic (18)
- # pathom (29)
- # pedestal (6)
- # portal (34)
- # reagent (2)
- # reitit (4)
- # releases (1)
- # sci (10)
- # shadow-cljs (7)
- # tools-deps (4)
- # vim (6)
Can someone confirm this easily? I inject logging functions into my SCI context. Then I evaluate code in that context that defines a function which uses the logging functions. I store the resulting context where the function is defined for later use. Now my question is, if I fork the context, and re-define the logging functions (with more context available at this time), does my function refer to the old logging functions or the new ones? From my experiments it seems like the function defined in the forked context still refers to the old logging functions, and the new ones are not used.
I think it's easier to understand what you are talking about if you make a small repro in working code
Ok, something like this
(defn info1 [& args] (apply prn "info1" args))
(defn info2 [& args] (apply prn "info2" args))
(def sci-ctx1
(sci/init {:namespaces {'log {'info info1}}}))
(def sci-ctx2
(let [ctx (-> sci-ctx1 sci/fork)]
(sci/eval-string* ctx "(defn hello [x] (log/info \"hello\" x))")
ctx))
(def sci-ctx3
(-> sci-ctx2
sci/fork
(sci/merge-opts {:namespaces {'log {'info info2}}})))
(sci/eval-string* sci-ctx3 "(hello \"world\")")
; => "info1" "hello" "world"
My initial expectation was that it would print "info2"
because that binding is meant to override the previous binding of log/info
in the context but the hello
function maintains reference to the old one.
How it works is this:
You provide log/info
as raw function, not as a SCI var
When hello
is analyzed it references this function directly, so no matter what changes are made later on, it will always hold on to the same function.
Maybe a solution to your problem would be:
(ns scratch
(:require [sci.core :as sci]))
(def ^:dynamic *log-fn* prn)
(defn info1 [& args] (apply *log-fn* "info1" args))
(def sci-ctx1
(sci/init {:namespaces {'log {'info info1}}}))
(def sci-ctx2
(let [ctx (-> sci-ctx1 sci/fork)]
(sci/eval-string* ctx "(defn hello [x] (log/info \"hello\" x))")
ctx))
(binding [*log-fn* identity]
(sci/eval-string* sci-ctx2 "(hello \"world\")"))