They may be semantically distinct and part of the type system, but they are not 
types.  I don’t think they should be given the privilege of overloading, but 
this is a separate discussion.

~Robert Widmann

> On Jun 13, 2017, at 11:00 AM, John McCall <[email protected]> wrote:
> 
>> On Jun 13, 2017, at 1:48 PM, Beta <[email protected] 
>> <mailto:[email protected]>> wrote:
>> I would like to note that overloading on inout is a code smell and something 
>> that should be removed in a future version of the language.  inout is not a 
>> type, it’s a SIL type residency annotation.
> 
> Uh, no, inout arguments are semantically extremely different from by-value 
> arguments, and this is very much part of the type system.
> 
> John.
> 
>> 
>> ~Robert Widmann
>> 
>>> On Jun 13, 2017, at 10:40 AM, Xiaodi Wu via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> Note that “inout Void” is a distinct type from “Void”; it is not possible 
>>> to specify a default value for an inout Void parameter even explicitly 
>>> (“error: cannot pass immutable value of type ()...”), so naturally it 
>>> cannot be done implicitly either.
>>> On Tue, Jun 13, 2017 at 12:29 Jens Persson <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> The std lib swap could perhaps be an interesting example to consider:
>>> public func swap<T>(_ a: inout T, _ b: inout T)
>>> 
>>> What would happen with that?
>>> Will inout arguments be an exception to the rule of Void getting a default 
>>> value, and if so, what would the effects of that be?
>>> Or would it somehow be allowed to call swap()?
>>> Or is there a third alternative?
>>> /Jens
>>> 
>>> On Tue, Jun 13, 2017 at 7:15 PM, John McCall via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>>> On Jun 13, 2017, at 4:41 AM, Xiaodi Wu <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>> On Tue, Jun 13, 2017 at 3:06 AM, John McCall <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>>> On Jun 13, 2017, at 3:30 AM, Jérémie Girault <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> Exactly, 
>>>>> The reflexion behind it is: 
>>>>> 
>>>>> - Let's understand that 0110 and other tuple SE are important for the 
>>>>> compiler, we do not want them to rollback
>>>>> - However we have number of regressions for generics / functional 
>>>>> programmers
>>>>> - Let’s solve this step by step like a typical problem
>>>>> 
>>>>> - Step 0 is adressing this Void tuple of size zero :
>>>>>   - Zero is in many problems of CS an edge case, so let’s handle this 
>>>>> case first
>>>>>   - The compiler knows what Void is, and its only value (or non-value)
>>>>>   - It was handled historically by the compiler because of implicit side 
>>>>> effects
>>>>>   - Let’s handle it explicitely with rules in current context
>>>>>   - one effect of the proposal is source compatibility
>>>>>   - but the goal is to build atop and strengthen 0110, 0066 and other 
>>>>> tuple-related SE
>>>>> 
>>>> 
>>>> There are four difficulties I see with this proposal.
>>>> 
>>>> The first is that it is a first step that quite clearly does not lead to 
>>>> anything.  It resolves a difficulty with exactly one case of function 
>>>> composition, but we would need completely different solutions to handle 
>>>> any of the other compositional regressions of SE-0110.
>>>> 
>>>> The second is that it's a huge source of complexity for the type system.  
>>>> The type checker would not be able to do even rudimentary type matching, 
>>>> e.g. when checking a call, without having first resolved all of the 
>>>> argument and parameter types to prove that they are not Void.  This would 
>>>> probably render it impossible to type-check many programs without some 
>>>> ad-hoc rule of inferring that certain types are not Void.  It would 
>>>> certainly make type-checking vastly more expensive.
>>>> 
>>>> The third is that it is not possible to prevent values of Void from 
>>>> existing, because (unlike Never, which cannot be constructed) they are 
>>>> always created by returning from a Void-returning function, and a generic 
>>>> function can do anything it likes with that value — turn it into an Any, 
>>>> store it in an Array, whatever.  The proposal seems to only consider using 
>>>> the value as a parameter.
>>>> 
>>>> Hang on, though. If Jérémie is interested only in addressing the issue of 
>>>> Void as a parameter and his idea can be adequately carried out by 
>>>> inferring a default value of Void for every parameter of type Void, this 
>>>> should be a fairly self-contained change, should it not? And would the 
>>>> impact on the cost of type checking really be vastly greater in that case?
>>> 
>>> If the proposal was phrased in terms of defaults, e.g. "trailing parameters 
>>> do not require a matching argument if they have Void type", then yes, that 
>>> would be implementable because it still admits a "local" reduction on call 
>>> constraints, one which does not need to immediately reason about the actual 
>>> types of arguments.  It is not clear that this rule allows function 
>>> compositions of the sort that Jérémie is looking for, though.
>>> 
>>> Anyway, that is not the proposal; the proposal is that parameters — in any 
>>> position — are simply removed from the parameter sequence if they have Void 
>>> type.  In order to allow composition (i.e. f(g(x)), where g: X -> Void), 
>>> you then need a matching rule that arguments are dropped from the argument 
>>> sequence (for purposes of type-checking) if they have Void type.  Either of 
>>> these rules is sufficient to turn the reduction of function-type matches 
>>> into an extremely messy combinatoric matching problem where e.g. (τ0, Int) 
>>> can be passed to a function taking (Int, τ1) if we can decide that τ0 == τ1 
>>> == Void.
>>> 
>>>> This idea is now rather intriguing to me because it extends beyond just 
>>>> addressing one symptom of SE-0110. Swift allows us to omit the spelling 
>>>> out of return types that are Void, it allows warning-free discarding of 
>>>> return values that are Void, etc. This could add a nice consistency and 
>>>> rationalize some of the weirdness of passing a value that is stipulated by 
>>>> the parameter type.
>>>> 
>>>> Finally, it would allow a lot of inadvertent errors with the use of 
>>>> generic functions, because any argument of unconstrained type could be 
>>>> accidentally specialized with Void.  For example, if you forgot to pass an 
>>>> argument to this function, it would simply infer T=Void:
>>>>   func append<T>(value: T)
>>>> It seems more likely that this would lead to unexpected, frustrating bugs 
>>>> than that this would actually be desired by the programmer.  You really 
>>>> just want this to kick in in more generic situations.
>>>> 
>>>> Hmm, at first glance, that seemed like it could be bad. But if, say, a 
>>>> particular collection can store an element of type Void, is it so 
>>>> undesirable to allow `append()` to append Void?
>>> 
>>> append on a Collection is not an unconstrained generic; its parameter type 
>>> is determined by the type of the collection.  Perhaps this was a 
>>> poorly-chosen example.
>>> 
>>> John.
>>> 
>>>> 
>>>> 
>>>> John.
>>>> 
>>>>> 
>>>>> —
>>>>> very short reply expected - vsre.info <http://vsre.info/>
>>>>> Jérémie Girault
>>>>> 
>>>>> On 13 juin 2017 at 00:44:52, Xiaodi Wu ([email protected] 
>>>>> <mailto:[email protected]>) wrote:
>>>>> 
>>>>>> On Mon, Jun 12, 2017 at 5:38 PM, Xiaodi Wu <[email protected] 
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> On Mon, Jun 12, 2017 at 5:25 PM, Jérémie Girault 
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>> 
>>>>>> —
>>>>>> very short reply expected - vsre.info <http://vsre.info/>
>>>>>> Jérémie Girault
>>>>>> 
>>>>>> On 12 juin 2017 at 23:56:37, Xiaodi Wu ([email protected] 
>>>>>> <mailto:[email protected]>) wrote:
>>>>>> 
>>>>>>> On Mon, Jun 12, 2017 at 4:47 PM, Jérémie Girault 
>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>> - Void as arguments is pretty common when using generics, that’s a core 
>>>>>>> point of this proposal. An maybe that’s why we misunderstood ourselves 
>>>>>>> (around 0110 / 0066). This proposal addresses arguments.
>>>>>>> - maybe it should be revised around this ? Simple example : 
>>>>>>> 
>>>>>>> `typealias Callback<T> = (T) -> Void` -> `Callback<Void>` will give 
>>>>>>> `(Void) => Void`. 
>>>>>>> 
>>>>>>> It was acceptable before swift4 but no more. However nobody cares about 
>>>>>>> this `Void` argument and actually we know it’s value. So why let the 
>>>>>>> developer type it ?
>>>>>>> 
>>>>>>> Ah, I see. The purpose of SE-0029...SE-0110 was to make it possible to 
>>>>>>> distinguish an argument list `(Void)` from an argument list `()`. This 
>>>>>>> does cause some verbosity where previously users relied on implicit 
>>>>>>> tuple splatting. Ideally, we would bring back some syntactic sugar to 
>>>>>>> make this more ergonomic. But, whether or not the spelling is made more 
>>>>>>> user-friendly, the point here is that _everybody_ should care about 
>>>>>>> this `Void` argument.
>>>>>> 
>>>>>> It is still be typechecked and appropriate errors should be reported to 
>>>>>> the user so _nobody_ will ignore it.
>>>>>> 
>>>>>> But with the proposal the code will be striped out of Void arguments at 
>>>>>> compile-time. I think it's a win for the developer on a lot of grounds. 
>>>>>> The fact that this proposal integrates with the type-system is also 
>>>>>> important.
>>>>>> 
>>>>>> If you are not comfortable about Void being stripped, we can also 
>>>>>> discuss alternatives: someone was suggesting me that it would be 
>>>>>> possible to replace :
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> func foo<T, U, V>(t: T, u: U) -> V {
>>>>>> 
>>>>>>   // do something with t and u
>>>>>> 
>>>>>>   // return some V
>>>>>> 
>>>>>> }
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> with
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> func foo<Void, Int, String>(u: Int) -> String { let t = ()
>>>>>> 
>>>>>>   // do something with t and u
>>>>>> 
>>>>>>   // return some V
>>>>>> 
>>>>>> }
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> or
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> func foo<Void, Int, String>(t: Void = (), u: Int) -> String {
>>>>>> 
>>>>>>   // do something with t and u
>>>>>> 
>>>>>>   // return some V
>>>>>> 
>>>>>> }
>>>>>> 
>>>>>> ```
>>>>>> 
>>>>>> I don’t know what you would consider more effective or elegant (at an 
>>>>>> implementation level) but it’s the same result for the developper.
>>>>>> 
>>>>>> 
>>>>>> Ah, but I think I catch your drift with the last example. Is this a more 
>>>>>> general point that the compiler should treat every parameter of type 
>>>>>> Void as having an implied default value of Void? That would be an 
>>>>>> interesting idea.
>>>>>> 
>>>>>> What is the goal of such changes? Is it to allow you to write `foo()` 
>>>>>> instead of `foo(())` for a function `foo` of type `(T) -> Void`?
>>>>>> 
>>>>>> If so, then I think what you're seeking to do is reverse SE-0066 (as 
>>>>>> Vladimir points out), which explicits details how it's is an intentional 
>>>>>> change to require such a spelling. I think you're starting from the 
>>>>>> premise that this is unintended or undesirable, when in fact it is 
>>>>>> deliberate and approved.
>>>>>> 
>>>>>> It is also, unless I'm mistaken, not the issue that was raised initially 
>>>>>> with respect to SE-0110, which had to do with the extra boilerplate of 
>>>>>> destructuring a tuple inside a closure, something that was not so 
>>>>>> obvious before implementation.
>>>>>> 
>>>>>>> My point here is that `Void` should be “striped” by “reducing” argument 
>>>>>>> list signatures.
>>>>>>> 
>>>>>>> —
>>>>>>> very short reply expected - vsre.info <http://vsre.info/>
>>>>>>> Jérémie Girault
>>>>>>> 
>>>>>>> On 12 juin 2017 at 19:15:18, John McCall ([email protected] 
>>>>>>> <mailto:[email protected]>) wrote:
>>>>>>> 
>>>>>>>> 
>>>>>>>>> On Jun 12, 2017, at 4:48 AM, Jérémie Girault via swift-evolution 
>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>> 
>>>>>>>>> Hi here,
>>>>>>>>> 
>>>>>>>>> As I tested swift4 in xcode9b1 I noticed a lot of regressions about 
>>>>>>>>> tuples usage.
>>>>>>>>> 
>>>>>>>>> After documenting myself about the changes which happened, I thought 
>>>>>>>>> that they could be improved. Instead of fighting these propositions 
>>>>>>>>> (which make sense), I wanted create a few proposal which would 
>>>>>>>>> improve these recent changes with a few simple rules.
>>>>>>>>> 
>>>>>>>>> My propositions are based on the recent decisions and in the 
>>>>>>>>> continuation of SE-0110. The first one is about Void.
>>>>>>>>> Void is historically defined as the type of the empty tuple. The 
>>>>>>>>> reason of this is that arguments were initially considered as tuple.
>>>>>>>> 
>>>>>>>> The dominant consideration here was always return types, not 
>>>>>>>> parameters.  I'm not sure there was ever much point in writing Void in 
>>>>>>>> a parameter list, but whatever reasons there were surely vanished with 
>>>>>>>> SE-0066.
>>>>>>>> 
>>>>>>>> Note that 'void' in C was originally exclusively a return type.  ANSI 
>>>>>>>> gave it a new purpose it with void*, but the meaning is totally 
>>>>>>>> unrelated.
>>>>>>>> 
>>>>>>>> John.
>>>> 
>>>> 
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to