-
Notifications
You must be signed in to change notification settings - Fork 8
Description
In #69 we've been discussing the problem that the current version of protocols is constructor-centric, with provided members being added/checked on .prototype and only static members on the object itself, which means the implements operator does not work on instances. Another idea has been to default to adding provided members on the object itself, and static members on .constructor which would mean doing Protocol.implement(C.prototype, P) to get the current functionality.
While I would be opposed to dropping static with no alternative, because I think it's important for protocols to be atomic (you should not need to pull in multiple protocols to implement a single piece of functionality), I wonder if we could generalize it and make this a user choice.
Reusing static made a lot of sense when keeping syntax close to class definitions was a design goal.
However, with protocols progressively being a larger departure from class syntax (we recently resolved they cannot use class fields, we've been discussing dropping extends, etc), reusing static seems to provide less value.
What if instead of static, we supported a concept of "some provided members are attached to subobjects"?
I.e. instead of this:
protocol P {
foo () {}
static bar () {}
}To be able to do Protocol.implement(C, P), you'd have this:
protocol P {
on prototype {
foo () {}
}
// implicit on this
bar () {}
}Or, to enable Protocol.implement(C.prototype, P) (which would also make c implements P possible) you'd define it like this:
protocol P {
foo() {}
on constructor {
bar () {}
}
}Any on xxx members could become implicit requires, perhaps with the additional constraint of being objects.
Then whether to define a constructor-first protocol or an object/instance focused protocol becomes a user choice, rather than a language choice.
With sufficient introspection (#55), you could even create a protocol that turns another protocol "inside out", having both versions.
There could also be a requires on syntax for required members.
The class head syntax would just assume one of the two formats (probably the one that is installed on prototypes).
In addition to addressing the instance/static conundrum, this allows expressing protocols that are not currently possible to express, as they depend on requiring subobject members or installing members on subobjects.