Fork me on GitHub
#sci
<
2021-08-20
>
phronmophobic23:08:48

I finally got around to packaging the ability to patch protocols to work with both sci values and "outside" values and allow for extension within sci. Is that something that might be a good fit to pull into sci itself? If it does, I can work on a pull request. Otherwise, I'll probably release it in a standalone library. example usage:

(def opts
  {:namespaces
   (merge (do
            (scify/scify-ns-protocols 'membrane.ui)
            (scify/ns->ns-map 'membrane.ui))
          (scify/ns->ns-map 'membrane.component))})
scify/ns->ns-map creates a map from an existing ns for use in sci scify/scify-ns-protocols will replace protocols with versions that work inside and outside of sci and allow for extension. idempotent. code: https://github.com/phronmophobic/mobiletest/blob/main/src/com/phronemophobic/mobiletest/scify.clj

borkdude07:08:02

I'll have a look at this soon, currently on a trip

👍 2
borkdude21:08:26

OK, so you are patching the original protocol vars. Nice! Just curious, does that also work with direct linking?

phronmophobic21:08:52

tbh, I'm not exactly sure why. maybe it's because defprotocol uses intern to create the protocol method vars?

borkdude21:08:26

That surprises me. What if you have a library which calls a protocol function like (defn library-fn [] (proto-fn :bar)) and you patch the var, and then your SCI program implements this protocol function on some type that wasn't implement before, I would expect that library-fn wouldn't be affected by this, with direct linking?

borkdude21:08:20

then again, I'm not completely sure, perhaps protocol vars aren't prone to direct linking

phronmophobic21:08:36

I think it's that protocol vars aren't directly linked

phronmophobic21:08:41

otherwise, you couldn't patch it in the first place

borkdude21:08:39

ah you are patching the protocol var, but not the vars that represent the functions, right?

borkdude21:08:59

seems you're doing both

phronmophobic21:08:27

I'm altering the meta for the protocol itself, but not its value

phronmophobic21:08:37

all the protocol methods get patched though

phronmophobic21:08:53

altering the protocol's meta is really only for bookkeeping: • patch only once • mark patched protocols for ns->ns-map

borkdude22:08:06

yeah, it seems like direct linking doesn't affect protocol vars:

$ clj -J-Dclojure.compiler.direct-linking=true
Clojure 1.10.1
user=> (defn foo [] :foo)
#'user/foo
user=> (defn bar [] (foo))
#'user/bar
user=> (bar)
:foo
user=> (defn foo [] :bar)
#'user/foo
user=> (bar)
:foo
user=> (defprotocol Foo (pfoo [this]))
Foo
user=> (defn libfn [x] (pfoo x))
#'user/libfn
user=> (extend-protocol Foo String (pfoo [_] :dude))
nil
user=> (libfn "hello")
:dude
user=> (:method-builders Foo)
{#'user/pfoo #object[user$eval152$fn__153 0x3157e4c0 "user$eval152$fn__153@3157e4c0"]}
user=> (alter-var-root #'user/pfoo (fn [old] (fn [this] (prn :this) (old this))))
#object[user$eval178$fn__179$fn__180 0x18eec010 "user$eval178$fn__179$fn__180@18eec010"]
user=> (libfn "hello")
:this
:dude

🤷 2
borkdude22:08:20

perhaps because they are extensible, you can't refer directly to what's in the var

borkdude22:08:59

and the var is updated each time there is a new protocol impl

borkdude22:08:37

user=> user/pfoo
#object[user$eval152$fn__153$G__143__158 0x26f7cdf8 "user$eval152$fn__153$G__143__158@26f7cdf8"]
user=> (extend-protocol Foo clojure.lang.Keyword (pfoo [_] :num))
nil
user=> user/pfoo
#object[user$eval152$fn__153$G__143__158 0x35dd9ed3 "user$eval152$fn__153$G__143__158@35dd9ed3"]

borkdude22:08:53

It seems the hash/memory location (what is this again?) changes but not the object itself?

phronmophobic22:08:44

it's not totally clear to me how it works. > Additionally, the compiler can remove unused vars from class initialization and direct linking will make many more vars unused. https://clojure.org/reference/compilation#directlinking My best guess is that however protocols are implemented causes the vars to used and included when compiled

borkdude22:08:37

It might be good to verify this in http://ask.clojure.org wether we can rely on this

phronmophobic22:08:55

ok, asking now

borkdude06:08:56

Cool, let’s wait :)

phronmophobic22:08:45

we got an answer. what do you think?

borkdude08:08:12

Yeah, I think it's good to rely on the state of the Clojure compiler for now that it won't be directly linked. Your solution relies on SCI building protocols on multi-methods which also isn't guaranteed to stay the same (it's an impl detail which happened to work very well with native image) but may change in the future (e.g. when GraalvM exposes other ways to accomplish the same thing) - also not very likely but still. So for now, I think it's good to use this code perhaps in a lib, but not yet as part of the SCI API. We can however add it in the documentation or wiki in a tips and tricks section.

👍 1