clj-commons / potemkin

some ideas which are almost good
572 stars 53 forks source link

Empty defprotocol+ bodies cause definition to not occur #44

Closed WilliamParker closed 2 years ago

WilliamParker commented 8 years ago

When defprotocol+ is called with just a name the protocol isn't actually created.

potemkin=> (defprotocol+ SomeProtocol)
nil
potemkin=> SomeProtocol

CompilerException java.lang.RuntimeException: Unable to resolve symbol: SomeProtocol in this context, compiling:(/private/var/folders/3m/tvc28b5d7p50v5_8q5ntj0pmflbdh9/T/form-init5752369463507367463.clj:1:5505) 
potemkin=> (defprotocol+ SomeProtocol2 "Doc string")
SomeProtocol2
potemkin=> SomeProtocol2
{:doc "Doc string"
 :method-builders {}
 :method-map {}
 :on potemkin.SomeProtocol2
 :on-interface potemkin.SomeProtocol2
 :sigs nil
 :var #'potemkin/SomeProtocol2}

The root cause of this is that prev-body will be nil when the protocol doesn't already exist, which will be equal to the body when just the name is present.

We can avoid this by just adding a docstring, as the REPL session above shows, but ideally defprotocol+ would behave in the same way as defprotocol from clojure.core. See http://dev.clojure.org/jira/browse/CLJ-966

potemkin=> (clojure.core/defprotocol NormalProtocol)
NormalProtocol
potemkin=> NormalProtocol
{:method-builders {}
 :method-map {}
 :on potemkin.NormalProtocol
 :on-interface potemkin.NormalProtocol
 :sigs nil
 :var #'potemkin/NormalProtocol}

Our use case for this was somewhat odd; we basically have a protocol that we want to remove but it still needs to be resolvable. The only usages were inside a macro that we control, so we can just get rid of it and substitute something else, but we still need to have a Var and a class of the same name that are resolvable.

WilliamParker commented 8 years ago

I submitted a pull request for this at https://github.com/ztellman/potemkin/pull/45

KingMob commented 2 years ago

Fixed by #45