[CLJS-414] Implement specify, allowing instances to implement protocols Created: 30/Oct/12 Updated: 03/May/13 |
|
| Status: | Open |
| Project: | ClojureScript |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Enhancement | Priority: | Major |
| Reporter: | Herwig Hochleitner | Assignee: | Herwig Hochleitner |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
| Description |
|
Javascript objects are fully dynamic. Currently, ClojureScript has no mechanism to exploit that for protocol implementation.
extend-type can be implemented in terms of specify (by specifying the .prototype), but extend-type has grown from its humble beginnings
and all that in a single macro body. So this is also a good opportunity to do some refactoring. specify should have an interface similar to extend-type. Additionally a lower level operation is needed to attach existing lambdas as protocol methods. It's called specify* in my current implementation. It takes a lambda for every specified protocol-method-arity, with a syntax loosely based on clojure.core/extend. |
| Comments |
| Comment by Herwig Hochleitner [ 30/Oct/12 11:21 PM ] |
|
First patch implements specify, second switches extend-type to use it. |
| Comment by David Nolen [ 31/Oct/12 9:30 AM ] |
|
This is a big patch so it's going to take time to review. First question, if we're going to follow the footsteps of extend what's the purpose of changing the syntax like having to specify a map of arities? |
| Comment by Herwig Hochleitner [ 31/Oct/12 10:32 AM ] |
|
The reason is that I wanted specify* to do as little as possible. It's basically just an abstraction over the name mangling for protocol methods, which was completely hidden till now. One of the purported use cases is: (def methA-1 [this] ...) (def methA-2 [this x] ...) (def methB-1 [this] ...) (defn specify-to-P [o] (specify* o P {methA {1 methA-1 2 methA-2} methB {1 methB-1}})) Here the method bodies are not allocated every time specify-to-P is called, as opposed to what the more high-level specify would do. If we didn't know which arities are to be generated, there would be simply no way to infer it:
EDIT: As for using symbols instead of keywords: I could do this, since specify* is a macro, not a function. |
| Comment by Herwig Hochleitner [ 31/Oct/12 12:59 PM ] |
|
That way we could support consumers that want to determine the set of implemented protocols at runtime, similar to extend. This can be a separate ticket where we work out whether it's :method 'method or "method". As for specify* using symbols: My gut feeling tells me that since it will always be a compiler macro (or builtin) and takes the arities, there is no merit in making it superficially more similar to extend. OTOH, it occurs to me that given specify-method, we could leave out specify* completely. I think I'll try that when I get home from work. Thoughts on that approach? |
| Comment by Herwig Hochleitner [ 31/Oct/12 7:59 PM ] |
|
Actually, I had a rationale for using symbols in specify*, which I just now rediscovered while trying to implement aforementioned specify-method. This is also the real reason specify* (or specify-method) can't be a function: It would need a reflective layer to go from [proto method arity] to the gclosure minified version of $proto$method$arity$a. We don't have that in clojurescript, since it would considerably add to the output size. Considering that all, I think specify* in the current form is appropriate after all. Nevertheless I found an unrelated issue in the patch where 'Object would be resolved (with an unused result), triggering a warning. I added the 0001_1 patch, which supersedes 0001 and is functionally equivalent modulo the warning issue. 0002 still applies. |
| Comment by Herwig Hochleitner [ 01/Nov/12 12:09 AM ] |
|
Attached patch set 01** supersedes patch set 00** The differences are
|
| Comment by Herwig Hochleitner [ 03/Nov/12 12:53 AM ] |
|
Set up a design page http://dev.clojure.org/display/design/specify+i.e.+reify+for+instances |
| Comment by Herwig Hochleitner [ 04/Nov/12 10:06 PM ] |
|
Attached patch 0104, applies on top of other 01* patches. |
| Comment by Herwig Hochleitner [ 03/May/13 7:30 PM ] |
|
rebased to current master |