On Mon, Dec 26, 2016 at 12:50 AM, Daniel Leping <[email protected]> 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). > Well, this sounds very different from Adam's proposal, where he proposes semantic meaning for `init()` that, as he described, means that it cannot apply to every type that implements `init()`. However, he also just said that he thinks that all types with `init()` should conform, so I guess I'm confused which way that is. At base, you want a way of knowing if a type has `init()`. That sounds like reflection to me, not protocol conformance. For the record, I look forward to the day when AnyObject magic is removed; I assume it is coming eventually. On Mon, 26 Dec 2016 at 11:14 Xiaodi Wu <[email protected]> wrote: > >> On Mon, Dec 26, 2016 at 12:43 AM, Daniel Leping via swift-evolution < >> [email protected]> 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 < >> [email protected]> 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 < >> [email protected]> wrote: >> >> >> >> >> on Sun Dec 25 2016, Daniel Leping <[email protected]> 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 <[email protected]> wrote: >> >> >> > >> >> >> >> On Sun, Dec 25, 2016 at 10:50 PM, Daniel Leping >> >> >> >> <[email protected]> >> >> >> >> 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 <[email protected]> wrote: >> >> >> >> >> >> >> >> On Sun, Dec 25, 2016 at 10:18 PM, Daniel Leping >> >> >> >> <[email protected]> >> >> >> >> 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 <[email protected]> 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 >> >> >> >> <[email protected]> >> >> >> >> 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 < >> >> >> >> [email protected]> 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 <[email protected]> >> wrote: >> >> >> >> >> >> >> >> On Sun, Dec 25, 2016 at 7:30 PM, Adam Nemecek <[email protected]> >> >> >> >> 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 <[email protected]> >> wrote: >> >> >> >> >> >> >> >> On Sun, Dec 25, 2016 at 5:27 PM, Adam Nemecek <[email protected]> >> >> >> >> 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 >> >> >> > [email protected] >> >> >> > https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> > >> >> >> >> >> >> -- >> >> >> -Dave >> >> >> >> >> >> _______________________________________________ >> >> >> swift-evolution mailing list >> >> >> [email protected] >> >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >> >> >> _______________________________________________ >> >> swift-evolution mailing list >> >> [email protected] >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >> >> _______________________________________________ >> >> >> swift-evolution mailing list >> >> >> [email protected] >> >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >>
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
