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]> wrote: > > On Jun 13, 2017, at 4:41 AM, Xiaodi Wu <[email protected]> wrote: > > On Tue, Jun 13, 2017 at 3:06 AM, John McCall <[email protected]> wrote: > >> On Jun 13, 2017, at 3:30 AM, Jérémie Girault <[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 >> Jérémie Girault >> >> On 13 juin 2017 at 00:44:52, Xiaodi Wu ([email protected]) wrote: >> >> On Mon, Jun 12, 2017 at 5:38 PM, Xiaodi Wu <[email protected]> wrote: >> >>> On Mon, Jun 12, 2017 at 5:25 PM, Jérémie Girault <jeremie.girault@gmail >>> .com> wrote: >>> >>>> >>>> >>>> — >>>> very short reply expected - vsre.info >>>> Jérémie Girault >>>> >>>> On 12 juin 2017 at 23:56:37, Xiaodi Wu ([email protected]) wrote: >>>> >>>> On Mon, Jun 12, 2017 at 4:47 PM, Jérémie Girault <jeremie.girault@gmail >>>> .com> 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 >>>>> Jérémie Girault >>>>> >>>>> On 12 juin 2017 at 19:15:18, John McCall ([email protected]) wrote: >>>>> >>>>> >>>>> On Jun 12, 2017, at 4:48 AM, Jérémie Girault via swift-evolution < >>>>> [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] > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
