-
-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check order of protocol impls #378
Comments
It does look like the order is different in sci. It looks like extend-protocol has a higher priority than metadata definitions: (System/getProperty "babashka.version")
;; => "0.6.1"
(defprotocol Bar
:extend-via-metadata true
(bar [_]))
(def bar-map (with-meta {} {`bar (fn [_] {:impl :with-meta})}))
;; confirm extend-via-metadata does in fact work
(bar bar-map) ;; => {:impl :with-meta}
(defprotocol Foo
:extend-via-metadata true
(foo [_]))
(extend-protocol Foo
Object
(foo [_] {:impl :extend-protocol}))
(defrecord Fooer []
Foo
(foo [_] {:impl :defrecord}))
(def fooer (->Fooer))
(foo fooer);; => {:impl :defrecord}
(def foo-map (with-meta {} {`foo (fn [_] {:impl :with-meta})}))
;; confirm metadata
(meta foo-map)
;; => {user/foo
;; #object[sci.impl.fns$fun$arity_1__1208 0x3eac374a "sci.impl.fns$fun$arity_1__1208@3eac374a"]}
;; XXX expected :impl :with-meta, but extend-protocol for Object instead.
(foo foo-map)
;; => {:impl :extend-protocol}
(def fooer-vary-meta (vary-meta (->Fooer) assoc `foo (fn [_] {:impl :with-meta})))
(foo fooer-vary-meta);; => {:impl :defrecord}
(meta fooer-vary-meta)
;; => {:sci.impl/record true,
;; :type user/Fooer,
;; user/foo
;; #object[sci.impl.fns$fun$arity_1__1208 0x27dc294a "sci.impl.fns$fun$arity_1__1208@27dc294a"]}
;; note that using with-meta will overwrite the sci metadata for the defprotocol implementation
(def fooer-with-meta (with-meta (->Fooer) {`foo (fn [_] {:impl :with-meta})}))
(foo fooer-with-meta);; => {:impl :extend-protocol}
(meta fooer-with-meta)
;; => {user/foo
;; #object[sci.impl.fns$fun$arity_1__1208 0x437834e1 "sci.impl.fns$fun$arity_1__1208@437834e1"]}
(defrecord Barrer [] Bar (bar [_] {:impl :defrecord}))
(def barrer-vary-meta (vary-meta (->Barrer) assoc `bar (fn [_] {:impl :with-meta})))
(bar barrer-vary-meta);; => {:impl :defrecord}
(def barrer-with-meta (with-meta (->Barrer) {`bar (fn [_] {:impl :with-meta})}))
(bar barrer-with-meta);; => {:impl :with-meta}
|
Looks good to me! (System/getProperty "babashka.version");; => "0.6.2-SNAPSHOT"
(defprotocol Bar :extend-via-metadata true (bar [_]))
(def bar-map (with-meta {} {`bar (fn [_] :with-meta)}))
;; confirm extend-via-metadata does in fact work
(bar bar-map);; => :with-meta
(defrecord Barrer [] Bar (bar [_] :defrecord))
(def barrer-vary-meta (vary-meta (->Barrer) assoc `bar (fn [_] :vary-meta)))
(bar barrer-vary-meta);; => :defrecord
;; with-meta unsuprisingly overwrites the sci metadata that powers protocols
(def barrer-with-meta (with-meta (->Barrer) {`bar (fn [_] :with-meta)}))
(bar barrer-with-meta);; => :with-meta
(defprotocol Foo
:extend-via-metadata true
(foo [_]))
(extend-protocol Foo
Object
(foo [_] :extend-protocol))
(foo {});; => :extend-protocol
(defrecord Fooer []
Foo
(foo [_] :defrecord))
(foo (->Fooer));; => :defrecord
(def foo-map (with-meta {} {`foo (fn [_] :with-meta)}))
(foo foo-map);; => :with-meta
(def fooer-vary-meta (vary-meta (->Fooer) assoc `foo (fn [_] :vary-meta)))
;; works as expected: defrecord direct definition has priority over metadata
(foo fooer-vary-meta);; => :defrecord
What other edge cases are there? |
@grzm I would expect |
Ah, gotcha. I use extend and extend-type so infrequently I had forgotten about them. (defprotocol Baz (baz [_]))
(extend Object Baz {:baz (fn [_] :extend)})
;; OK
(baz {});; => :extend
;; XXX should be vary-meta
(baz (vary-meta {} assoc `baz (fn [_] :vary-meta)));; => :extend
(defprotocol Quux (quux [_]))
(extend-type Object Quux (quux [_] :extend-type))
;; OK
(quux {});; => :extend-type
;; XXX should be :vary-meta
(quux (vary-meta {} assoc `quux (fn [_] :vary-meta)));; => :extend-type I'll see if I can't squeeze in a PR, though I'm at Strange Loop today and tomorrow, so don't wait on me if you're feeling the itch. |
@grzm No worries, those examples are sufficient for me to create tests. Have fun at STL! |
@grzm Should be fixed now. Also updated bb master. |
Awesome! Thanks, @borkdude 🚀 |
Shouldn't hurt to test the newest bb to double check :) |
Oh, I did 😛 : Not in anger, (it's the weekend), but I tested against snapshot and newish clojure.
|
You elided the number of passed results from Clojure, but I assume they were the same :) |
Actually, I didn't elide it, I just didn't print it. 😢 I think that's because babashka prints the output of the last expression, and clojure doesn't unless you explicitly tell it to (using
|
(I also didn't test the multi-arity versions, but it was enough to confirm behavior to my satisfaction) Thanks again! |
Oh I see, yeah that's actually a disputable behavior of bb, but nobody complained hard enough about it yet... I actually had to introduce more complicated changes to fix a regression for multi-arity but the tests all seem to work there as well in SCI. Thanks for bringing this to my attention. How is/was Strangeloop? |
I think the existing behavior is useful for bb! I wouldn't ask for it to be changed :)
Yeah, I saw that. Thanks for digging in!
|
https://clojure.org/reference/protocols#_extend_via_metadata
Check if this holds true in sci.
We should make test cases for each of these:
Failing example:
Expected:
:meta
The text was updated successfully, but these errors were encountered: