Ok, an example: func myFactory<T: DefaultConstructable>(c:T.Type) -> T { let t = T()
if let ini = t as? Initializable { ini.initialize(self) } if let co = t as? ContextAware { co.setContext(context) } //etc return t } On Mon, 26 Dec 2016 at 11:19 Daniel Leping <dan...@crossroadlabs.xyz> wrote: > I'm not arguing for implicit conformance in general, but I'm telling that > DefaultConstructable is the same basic level as AnyObject, which is > conformed implicitly. > > Shortly, I'm against implicit conformance in general. I'm positive with > "automatic compiler magic" conformance to DefaultConstructable for any > object having a default constructor as it really is a very basic stuff. > Otherwise you will have to add explicit conformance to it in almost every > class of yours (annoying). > > > On Mon, 26 Dec 2016 at 11:14 Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Mon, Dec 26, 2016 at 12:43 AM, Daniel Leping via swift-evolution < > swift-evolution@swift.org> wrote: > > Thank you, Adam! > > > Wait, are you arguing for implicit conformance or not? > > On Mon, 26 Dec 2016 at 11:12 Adam Nemecek via swift-evolution < > swift-evolution@swift.org> wrote: > > > Swift doesn't do implicit conformance. It always has to be declared > explicitly. I'm pretty sure Doug Gregor can explain why better than I > could. > > > I don't think Daniel was arguing for implicit conformance, he's saying > that if it makes sense for an object to have a default constructor, it > makes sense for it to conform to the protocol which I agree with 100%. > > On Sun, Dec 25, 2016 at 9:17 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote: > > > > > on Sun Dec 25 2016, Daniel Leping <swift-evolution@swift.org> wrote: > > > > > > > You are right, usually it's required to implement a protocol which is > not a > > > > good approach. The best is plain objects which can be used independently > of > > > > ORM if needed (as DTOs, i.e.). > > > > > > > > I was thinking of DefaultConstructable as a protocol automatically > applied > > > > to any class/struct having a default init, which is really logical for > > > > me. > > > > > > Swift doesn't do implicit conformance. It always has to be declared > > > explicitly. I'm pretty sure Doug Gregor can explain why better than I > > > could. > > > > > > > On Mon, 26 Dec 2016 at 9:41 Xiaodi Wu <xiaodi...@gmail.com> wrote: > > > > > > > >> On Sun, Dec 25, 2016 at 10:50 PM, Daniel Leping > > > >> <dan...@crossroadlabs.xyz> > > > >> wrote: > > > >> > > > >> Ok, an example from ORM. You have an entity factory with a virtual > (read, > > > >> overloadable in the subclasses) method populating the properties. > > > >> DefaultConstructable is a great choice here. Otherwise you will have to > > > >> force the users of your ORM to implement a certain protocol, which you > most > > > >> probably would like to avoid. > > > >> > > > >> > > > >> Sorry--I'm not very familiar with using Swift for ORM purposes. Why do > you > > > >> want to avoid having your users conform to a certain protocol? Wouldn't > the > > > >> users of your ORM have to conform to `DefaultConstructible` then? I'm > > > >> looking at Swift ORMs, and all require users to conform to a protocol or > > > >> inherit from a base class, typically named `Model` or similar. From a > quick > > > >> Google search: > > > >> > > > >> https://vapor.github.io/documentation/fluent/model.html > > > >> https://github.com/blitzagency/amigo-swift > > > >> > > > >> > > > >> In general I think the best showcase is generic factories. > > > >> > > > >> On Mon, 26 Dec 2016 at 9:02 Xiaodi Wu <xiaodi...@gmail.com> wrote: > > > >> > > > >> On Sun, Dec 25, 2016 at 10:18 PM, Daniel Leping > > > >> <dan...@crossroadlabs.xyz> > > > >> wrote: > > > >> > > > >> Usually it's a generic function that needs to return a value from some > > > >> other function or a default value (zero) in a case of some conditions. > > > >> Optional value is an arguable solution in quite some scenarios. Afaik, > > > >> sometimes it can be used for optional resolution. > > > >> > > > >> > > > >> Right, I'd agree that Optional is the idiomatic way to do it. Afaict, > > > >> there's not much you can do with a default value that you couldn't with > > > >> nil, unless you have some guarantee as to _what_ that default is; > however, > > > >> I'd expect that in every case that you can rely on a guarantee about a > > > >> default value which would be more useful than nil, it's going to require > > > >> more specific knowledge of your type than an all-encompassing > > > >> `DefaultConstructible` can provide. > > > >> > > > >> Also, generic factories. Widely used in ORM solutions. > > > >> > > > >> > > > >> Can you elaborate on this? Why is Optional not a solution here? > > > >> > > > >> > > > >> As mentioned above, algorythmical stuff that requires Zero. > > > >> > > > >> > > > >> I'm still not convinced there exist credible use cases that need to be > > > >> generic over both collections and floating point, for instance. In > fact, in > > > >> my experience, there are few math-heavy algorithms where one can ignore > > > >> even the distinction between integers and binary floating point. By the > > > >> time you get down to matrix math, you start to run into difficulties > that > > > >> require separate implementations for Float and Double. > > > >> > > > >> On Mon, 26 Dec 2016 at 8:38 Xiaodi Wu <xiaodi...@gmail.com> wrote: > > > >> > > > >> Can you give some examples of what you used this approach to do? > > > >> > > > >> > > > >> On Sun, Dec 25, 2016 at 9:49 PM, Daniel Leping > > > >> <dan...@crossroadlabs.xyz> > > > >> wrote: > > > >> > > > >> +1 to this approach. I remember I had to create it on my own for my > > > >> projects. Would be nice to have it out of the box. > > > >> > > > >> On Mon, 26 Dec 2016 at 8:11 Adam Nemecek via swift-evolution < > > > >> swift-evolution@swift.org> wrote: > > > >> > > > >> > Yes, those particular types have initializers that take no arguments. > > > >> That does not address my question. You merely restated your initial > > > >> observation that many types in Swift have implemented `init()`. > > > >> > > > >> Right, it's an empirical argument. > > > >> > > > >> > I didn't think the value returned by `init()` was regarded as any sort > > > >> of zero--or even any sort of "default." In fact, some types in > Foundation > > > >> have a static property called `default` distinct from `init()`. > > > >> > > > >> Let's not talk about those then. This would not apply to every single > type > > > >> in existence, as I've stated previously. > > > >> > > > >> > It gives you something different every time. How can this be squared > > > >> with your stated motivation regarding concepts of zero and concepts of > > > >> equality? > > > >> > > > >> Due to the fact that it's a resource, not a value. As I've stated above, > > > >> not all of this applies to types that are more resource-like. > > > >> > > > >> > Or, it's what you get because that's the most trivial possible string. > > > >> Quite simply, I do not think the designer of most types that implement > > > >> `init()` have paused to wonder whether the value that you get is the > > > >> identity element associated with the most useful and prominent operation > > > >> that can be performed on that type. I certainly never have. > > > >> > > > >> This is an appeal to tradition. > > > >> > > > >> > The statement I wrote was in JavaScript, so I'm not sure what you mean > > > >> by returning an optional. `[].reduce((a, b) => a + b)` results in an > > > >> error in JavaScript. In Swift, such a function may also be implemented > with > > > >> a precondition that the array is not empty and would not return an > optional. > > > >> > > > >> I was talking about their analogous swift implementations. > > > >> > > > >> > Can you give an example of an algorithm dealing with tensors where you > > > >> would use a `DefaultConstructible` generic over all types that have > > > >> `init()`, as opposed to working with the existing `Integer`, > > > >> `FloatingPoint`, and other numerical protocols? > > > >> > > > >> If it's implemented as either nested collections or numbers. > > > >> > > > >> > > > >> > > > >> On Sun, Dec 25, 2016 at 6:00 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > > >> > > > >> On Sun, Dec 25, 2016 at 7:30 PM, Adam Nemecek <adamneme...@gmail.com> > > > >> wrote: > > > >> > > > >> > Is it well settled, either in Swift or in C++/Rust/etc., that the > value > > > >> returned by a default initializer/constructor is regarded as an identity > > > >> element or zero? > > > >> > > > >> Int() == 0, String() == "" so to some extent by convention, a lot of > types > > > >> have a default value as is. > > > >> > > > >> > > > >> Yes, those particular types have initializers that take no arguments. > That > > > >> does not address my question. You merely restated your initial > observation > > > >> that many types in Swift have implemented `init()`. > > > >> > > > >> I didn't think the value returned by `init()` was regarded as any sort > of > > > >> zero--or even any sort of "default." In fact, some types in Foundation > have > > > >> a static property called `default` distinct from `init()`. In Rust, the > > > >> Default trait requires a function called `default()`, which is > documented > > > >> as being useful when you want "some kind of default value, and don't > > > >> particularly care what it is." > > > >> > > > >> I was asking whether there's some understanding, of which I've been > > > >> unaware, that the result of `init()` (or the equivalent in other > languages) > > > >> is expected to be some sort of zero or an identity element. I'm not > aware > > > >> of any evidence to that effect. Are you? > > > >> > > > >> > Is the thread that I get by writing `let t = Thread()` some kind of > zero > > > >> in any reasonable sense of the word? > > > >> > > > >> DefaultConstructibility makes less sense for types that represent some > > > >> sort of resource but make sense for things that are values. But even in > > > >> this case, Thread() gives you a default value for example if you are > > > >> working with a resizable collection of threads. > > > >> > > > >> > > > >> It gives you something different every time. How can this be squared > with > > > >> your stated motivation regarding concepts of zero and concepts of > equality? > > > >> > > > >> A better question is why does thread currently implement a default > > > >> constructor? > > > >> > > > >> > > > >> It's an initializer that takes no arguments, because none are needed > for a > > > >> new thread. How else would you write it? > > > >> > > > >> > Do you mean to argue that for an integer the additive identity should > be > > > >> considered "more prominent and useful" than the multiplicative identity? > > > >> I'm not aware of any mathematical justification for such a conclusion. > > > >> > > > >> I do. The justification is that if I call the default constructor of Int > > > >> currently, I get the value of 0. > > > >> > > > >> > > > >> This is backwards. Why do you believe that the value you obtain from > > > >> `init()` is intended to be an identity element at all, let alone the > most > > > >> important one? (It's also circular reasoning. Since `init()` only ever > > > >> gives you one value at a time, by your reasoning it demonstrates that > every > > > >> type must have one "more prominent and useful" identity, which is > begging > > > >> the question.) > > > >> > > > >> Which means that the binary operation must be addition. > > > >> > > > >> > > > >> Based on the value of `Int.init()`, you conclude that addition of > integers > > > >> is a "more prominent and useful" operation than multiplication? Again, > this > > > >> is backwards. Rather, we know that each numerical type belongs to > multiple > > > >> ring algebras; there is no basis for reckoning any as "more useful." > Since > > > >> `init()` can only ever give us one value at a time, we know that > `init()` > > > >> cannot give a value that is a meaningful default with respect to any > > > >> particular operation. > > > >> > > > >> If I call String() I get "" which is the identity of the + String > > > >> operation. > > > >> > > > >> > > > >> Or, it's what you get because that's the most trivial possible string. > > > >> Quite simply, I do not think the designer of most types that implement > > > >> `init()` have paused to wonder whether the value that you get is the > > > >> identity element associated with the most useful and prominent operation > > > >> that can be performed on that type. I certainly never have. > > > >> > > > >> > Going to your original example, I should add: other languages provide > a > > > >> version of `reduce` that doesn't require an initial result (for > instance, > > > >> JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the > > > >> element at array index 0 as the initial result, and the accumulator > > > >> function is invoked starting with the element at array index 1. This is > > > >> precisely equivalent to having `reduce` use the additive identity as the > > > >> default initial result when + is the accumulator function and the > > > >> multiplicative identity when * is the accumulator function (with the > > > >> accumulator function being invoked starting with the element at array > index > > > >> 0). It does not require a DefaultConstructible protocol. What more > > > >> ergonomic solution could be implemented using a monoidic wrapper type? > > > >> > > > >> These two will have different signatures. The reduce you describe > returns > > > >> an optional, > > > >> > > > >> > > > >> The statement I wrote was in JavaScript, so I'm not sure what you mean > by > > > >> returning an optional. `[].reduce((a, b) => a + b)` results in an error > > > >> in JavaScript. In Swift, such a function may also be implemented with a > > > >> precondition that the array is not empty and would not return an > optional. > > > >> > > > >> the other one would returns the default value. > > > >> > > > >> > > > >> In what scenario would you prefer to propagate a default after reducing > a > > > >> potential empty collection _without supplying an explicit default_ for > that > > > >> operation? This would certainly violate the Swift convention of not > > > >> defaulting to zero and, I suspect, most users of Swift would not regard > > > >> that as ergonomic at all. > > > >> > > > >> > > > >> Fundamentally the default constructibles are useful in numerical > > > >> computations e..g. dealing with tensors. > > > >> > > > >> > > > >> Can you give an example of an algorithm dealing with tensors where you > > > >> would use a `DefaultConstructible` generic over all types that have > > > >> `init()`, as opposed to working with the existing `Integer`, > > > >> `FloatingPoint`, and other numerical protocols? (I should also add, > FWIW, I > > > >> have never seen a generic algorithm written for integers or FP types > that > > > >> has preferred the use of `T()` over `0`.) > > > >> > > > >> > > > >> On Sun, Dec 25, 2016 at 3:30 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > > >> > > > >> On Sun, Dec 25, 2016 at 5:27 PM, Adam Nemecek <adamneme...@gmail.com> > > > >> wrote: > > > >> > > > >> > *Which* APIs become more ergonomic? > > > >> > > > >> I'll get back to this question in a second if I may. This would be a > > > >> longer discussion and I first want to make sure that before we get into > the > > > >> details that there is a possibility of this being introduced (I'm > asking if > > > >> violating the no zero defaults is more important than slightly more > > > >> ergonomic APIs). But to give a broad answer I think that the concept of > a > > > >> zero is closely related to the concept of equality (and all the things > that > > > >> build up on equality such as comparability and negation). > > > >> > > > >> > 1) How does this square with Swift’s general philosophy to not default > > > >> initialize values to “zero”? > > > >> > > > >> I actually wasn't aware of this philosophy. Despite this philosophy, > look > > > >> at how many types actually currently implement a default constructor. > > > >> > > > >> > > > >> (Not a rhetorical question:) Is it well settled, either in Swift or in > > > >> C++/Rust/etc., that the value returned by a default > initializer/constructor > > > >> is regarded as an identity element or zero? Is the thread that I get by > > > >> writing `let t = Thread()` some kind of zero in any reasonable sense of > the > > > >> word? > > > >> > > > >> > > > >> Also can I ask what's the motivation behind this philosophy? > > > >> I think that in Swift, default constructibility makes complete sense for > > > >> (most?) structs, maybe less so for classes. > > > >> > > > >> > 2) To your original example, it isn’t immediately clear to me that > > > >> reduce should choose a default identity. Some types (e.g. integers and > FP) > > > >> belong to multiple different ring algebras, and therefore have different > > > >> identity values that correspond to the relevant binary operations. > > > >> > > > >> This is a good point that I've considered as well but felt that for the > > > >> most part, there is one particular identity and associated operation > that > > > >> is more prominent and useful than others. Furthermore, modeling > different > > > >> algebras isn't mutually exclusive with writing generic algorithms that > rely > > > >> on this protocol, you can always introduce some monoidic wrapper type > that > > > >> defines the more appropriate default value and operation. > > > >> > > > >> > > > >> Do you mean to argue that for an integer the additive identity should be > > > >> considered "more prominent and useful" than the multiplicative identity? > > > >> I'm not aware of any mathematical justification for such a conclusion. > > > >> > > > >> Going to your original example, I should add: other languages provide a > > > >> version of `reduce` that doesn't require an initial result (for > instance, > > > >> JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the > > > >> element at array index 0 as the initial result, and the accumulator > > > >> function is invoked starting with the element at array index 1. This is > > > >> precisely equivalent to having `reduce` use the additive identity as the > > > >> default initial result when + is the accumulator function and the > > > >> multiplicative identity when * is the accumulator function (with the > > > >> accumulator function being invoked starting with the element at array > index > > > >> 0). It does not require a DefaultConstructible protocol. What more > > > >> ergonomic solution could be implemented using a monoidic wrapper type? > > > >> > > > >> > > > >> > > > > _______________________________________________ > > > > swift-evolution mailing list > > > > swift-evolution@swift.org > > > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > > > > > > > -- > > > -Dave > > > > > > _______________________________________________ > > > swift-evolution mailing list > > > swift-evolution@swift.org > > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > > > _______________________________________________ > > swift-evolution mailing list > > swift-evolution@swift.org > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > > _______________________________________________ > > > swift-evolution mailing list > > > swift-evolution@swift.org > > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution