[swift-evolution] [Pitch] Add the DefaultConstructible protocol to the standard library

Tony Allevato tony.allevato at gmail.com
Mon Dec 26 23:06:00 CST 2016


On Mon, Dec 26, 2016 at 8:47 PM Daniel Leping <daniel at crossroadlabs.xyz>
wrote:

> Tony,
>
> totally agree. The functional approach is great and it definitely is worth
> being a default way of thinking in Swift.
>
> From the API perspectives, though, it would still be good to have an
> overload that accepts a type. Consider it library's syntactic sugar, but
> still.
>
> Moreover, functional approach is usually quite some complicated for
> newbies which is not good for the library to be widely used.
>

Is asking a user to pass an initializer as an argument really more
complicated for a newcomer than requiring them to write an empty extension
to retroactively conform types they want to use with the factory to a new
protocol, though? I'd argue the opposite. Passing the initializer to the
factory makes the relationship between the two things very clear; relying
on a protocol constraint means that the conformance is applied far away
from the factory that requires it. In any case, neither retroactive
modeling nor initializers-as-functions is probably a "newbie" concept in
Swift so I would find it difficult to imagine that adoption of an API would
be harmed by choosing the latter.



> In general I don't think we should be limited in Swift to be _functional
> only_.
>
> On Tue, 27 Dec 2016 at 10:09 Tony Allevato <tony.allevato at gmail.com>
> wrote:
>
> On Mon, Dec 26, 2016 at 8:35 PM Daniel Leping <daniel at crossroadlabs.xyz>
> wrote:
>
> Tony, could you, please, share your approaches? Maybe it will open the
> door to finding an easy solution to the issue.
>
>
> ...and I'll tell you what it is since I fat-fingered the send button too
> soon. :)
>
> There have been a couple times where I've written code that needed to
> generically serve instances of a type T, and in each of those cases—thanks
> to Swift's support for first-class functions and
> initializers-as-functions—I found it to be cleaner to have my factory take
> a () -> T as a parameter and I pass T.init into that, rather than place
> constraints on T itself.
>
> This approach doesn't require imposing *any* additional constraints on T.
> Even though it's trivial to use an extension to add conformance like
> DefaultConstructible to many existing types, the latter approach excludes
> any type that does not make sense to have a default initializer, or where
> the default initializer isn't what you want to use. Maybe you want to have
> your factory use a static method to create the objects of a certain type
> instead: passing the function reference lets you do that. The function can
> even be a closure that captures outer context, letting your factory work
> for types that need additional parameters passed to the creation method.
>
> In general, I think talking about factories as "a thing that needs to call
> a specific initializer on a type" is a discussion motivated by patterns in
> other languages that are more restrictive than Swift. If you think of a
> factory instead as "something you can call that returns a T", the
> functional approach is *much* more powerful and general.
>
>
> On Tue, 27 Dec 2016 at 10:02 Tony Allevato <tony.allevato at gmail.com>
> wrote:
>
> On Mon, Dec 26, 2016 at 8:31 PM Daniel Leping via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Braeden, a good point as for inheritance. Totally agree here.
>
> Though the generic factory problem remains. Maybe it could be solved
> differently? Any ideas?
>
>
> As a matter of fact, I've used a different approach in some of my own
> projects that has ended up working out well.
>
>
>
> The only thing that pops up in mind right now is to have some "compiler
> magic" that deals with the constraints. Maybe a concrete class can fall
> into the category (be DefaultConstructable).
>
> Anyways, my point is that compile time constraints for a type that can be
> created with a default constructor are important for certain patterns. I'm
> not saying the protocol is the right or the only way, but I want to find a
> solution.
>
> On Tue, 27 Dec 2016 at 5:22 Braeden Profile via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I’m gonna do my best to explain my thoughts on this, as I just spent an
> hour reading the whole thread…………
>
> I’m -1 on adding the protocol DefaultConstructible to the standard library
> (especially under that name).  It doesn’t explain its semantics
> effectively.  I agree that a protocol should have definite semantics that
> are hopefully explained by the name.  This protocol fails that test—a
> default instance of value types is completely context-specific, and default
> class instances are just iffy to me.
>
> I’m firmly in the camp that you could create a protocol like this for your
> own project and apply it to the types you think semantically fit the
> purpose…
> protocol ZeroConstructible { init() }
> extension Int: ZeroConstructible {  }
> …but I wouldn’t do this myself, as there are too many use-cases with too
> many definitions of “default”.  What if I wanted Int to conform to
> multiple?  It only can have one init().  I’d do something like this…
> protocol ZeroConstructible { static func constructZero() }
> protocol UnsafeConstructible { static func constructUnsafe() }
> protocol FactoryConstructible { static func constructDefault() } // I’ve
> never needed to use a factory, myself...
> …and create those new functions when I conform my types to it.  It’s
> cumbersome, but correct.  As of yet, I’ve never needed to do such a thing,
> and nearly all the use-cases brought up in the thread can be solved with
> something of the like.
>
> Every “default" is context-dependant.
>
>
> Addressing other parts of the thread:
>
>
>    - I read a new name suggested for the protocol:  “Identity”.
>    Unfortunately, I associate that with the proposed protocol HasIdentity {
>    func === }, not a mathematical identity.
>    - DefaultConstructible could never be a normal protocol that magically
>    gets applied where init() exists.  protocol required inits are just
>    that—`required`.  If a superclass conforms to DefaultConstructible, every
>    subclass must, too!  This would give most every class tree the infinite
>    chain of `init()` that NSObject suffers from.
>    - AnyObject was used to justify compiler magic that could be applied
>    for DefaultConstructible.  I disagree that this is appropriate, as
>    AnyObject most certainly implies semantics.  Every AnyObject is a class,
>    with reference semantics, unsafe-weak-strong references, and more.  I could
>    not see definite semantics evolve for DefaultConstructible throughout the
>    whole discussion.
>
>
> That’s my two cents.  Granted, no one would be hurt by its addition except
> those who try to understand this protocol, but I want to avoid that chaos.
>
>
> _______________________________________________
>
> swift-evolution mailing list
>
> swift-evolution at swift.org
>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
>
>
> swift-evolution mailing list
>
>
> swift-evolution at swift.org
>
>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161227/6b037c2b/attachment-0001.html>


More information about the swift-evolution mailing list