Fork me on GitHub
#clojurescript
<
2022-10-07
>
mhuebert07:10:44

A question about :extend-via-metadata. Since satisfies? returns false for things that only implement a protocol via metadata, would one do something like (or (satisfies? TheProtocol x) (and (satisfies? IMeta x) (contains? (meta x) 'my-qualified/impl-name))) or is there a better way?

p-himik08:10:10

Sounds like would be more suitable for #C03S1KBA2.

thheller08:10:04

you can just call meta on anything so that extra satisfies check is a little redundant

1
thheller08:10:37

(or (satisfies? TheProtocol x) (contains? (meta x) 'my-qualified/impl-name))

seancorfield08:10:46

I would say that calling satisfies? in the first place is probably a code smell and would question why you were doing it?

mhuebert08:10:02

ah. I thought I had run into issues calling meta on things that don’t implement it but could just be my failing memory

seancorfield08:10:52

user=> (meta 42)
nil
user=> (meta "s")
nil
user=>
(in Clojure, at least, not sure about cljs but I'd expect the same)

mhuebert08:10:02

It’s a generic data-structure viewer which allows customizing/overriding views for particular types, so we can’t make any assumptions about what is being passed in

seancorfield08:10:31

@U050RLRRQ So this check is... where...? Protocols can be extended to Object so that would be the default case where no more specific protocol extension applies.

mhuebert08:10:57

ah i know where I got that idea from, with-meta

mhuebert08:10:03

but yes meta can be safely called

seancorfield08:10:23

meta includes a check on the type (in Clojure) and returns nil otherwise.

mhuebert08:10:16

we run values through a list of “viewers”, each of which can either handle the value or “pass” if it does not apply. the viewers can be dynamically rebound

mhuebert08:10:25

so we can’t only rely on implementing a single protocol as the viewers can take more than just an object’s type to decide whether they handle it or not

p-himik08:10:59

Could it be a good use case for "Ask For Forgiveness, Not Permission"?

thheller08:10:58

if you ask me this check is totally fine. you could skip it if you provide a default implementation, but that only makes sense if you control the full protocol

p-himik08:10:03

It was a general question, and I meant catching the exception that would be thrown if there's no implementation and treating it as "welp, seems like it doesn't satisfy the protocol after all".

thheller08:10:20

I'd assume the common case will not have this, so the exception will probably be the common case. but that assumption comes from building shadow-cljs Inspect. which may or may not apply elsewhere 😛

mhuebert08:10:54

yeah in the vast majority of cases a built-in viewer will be used, eg. inspecting common data structures (a generic map-viewer, list-viewer, etc), or a viewer for a custom type where we don’t need to use a protocol. But in certain cases we may want to view eg. a map differently without changing its value and so putting a viewer in its metadata can work nicely

mhuebert08:10:36

thank you everyone for your help

thheller08:10:44

but if there always is a default viewer then you can just call it? and let the metadata basically override it? so no need to check?

mhuebert08:10:14

not sure I follow exactly. if I call the. protocol’s fn on something that hasn’t implemented it, it will throw?

thheller08:10:20

no it'll throw if its not implemented. Just thought you have a extend-protocol for the common types already, and letting the metadata override that

borkdude11:10:25

Some people have also used the technique of adding a special method to the protocol isFoo or so and extend the protocol to Object and return false there, to bypass satisfies?. I'm not sure if that applies here.