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