[swift-evolution] [Pitch] Flattening the function type of unapplied instance methods

Joe Groff jgroff at apple.com
Thu Feb 25 18:57:00 CST 2016


> On Feb 25, 2016, at 4:22 PM, Chris Lattner <clattner at apple.com> wrote:
> 
> 
>> On Feb 25, 2016, at 9:13 AM, Joe Groff <jgroff at apple.com <mailto:jgroff at apple.com>> wrote:
>> 
>> 
>>> On Feb 24, 2016, at 8:50 PM, Chris Lattner <clattner at apple.com <mailto:clattner at apple.com>> wrote:
>>> 
>>> None of these are really great.  Since you’re advocating for it, I’m very concerned about making partially applied methods be uncurried always (#2).  I have seen a *lot* of people use curried methods on classes (in particular) and this leads to some pretty elegant patterns.  I’d expect any serious discussion of changing this behavior to include a survey of what people are actually using this for, and whether the end result we’d get from this change would be better or worse overall (not just in a single case).
>> 
>> I'm concerned about that too, but I think most of these use cases are already impeded by removing tuple argument splatting, since that makes it impossible to make a generic method transformation like `alterMethod<Receiver, Args, Ret>(method: Receiver -> Args -> Ret)`. I think these use cases can be recovered on flattened methods by explicit variadic splatting, since you could then write `alterMethod<Receiver, Args, Ret>(method: (Receiver, Args...) -> Ret)` instead.
> 
> I don’t really understand that, because the use-cases I’ve seen aren’t in generic context’s

Do you have an example in mind of a nongeneric use of curried methods that can't be easily rewritten in terms of a flat method type?

> , but let me step back and see if I understand your proposal.  Here’s your example again:


>> struct Bar {
>>   var x = 0
>>   mutating func bar() { x += 1 }
>> }
>> 
>> let a = Bar.bar
> 
> 
> I believe that you’re proposing that “a” have type "(inout Bar) -> ()” since the empty argument list got flattened into the self argument.
> 
> However, what is the type of the partial application case, i.e. “someBarInstance.bar”?
> 
> It seems that this *has* to be invalid for mutating methods, and it is the most commonly curried forms that I’ve seen for classes.

Yes, the partial application is not allowed. We currently incorrectly accept the fully applied reference `Bar.bar`. I agree that if we change nothing else, that's a hole we should plug.

> 
> I would be extremely nervous about saying that partial application and the raw name disagree, and I really wouldn’t want to kill partial application for classes and non-mutating methods.

We can decouple the meaning of `Type.instanceMethod` from the partial application `instance.instanceMethod`. Even if the type of `Type.instanceMethod` is flattened, we can still accept `instance.instanceMethod` with the current behavior. It's maybe a bit less elegant that `instance.instanceMethod` isn't just "sugar" for `Type.instanceMethod(instance)`, but that already isn't really the case for `mutating` methods—we treat a full application `instance.instanceMethod(foo)` as a single call for the purposes of the mutation model.

-Joe

> 
> I think that the least bad answer here is to just have sema reject attempts to get the base name of the mutating methods.  In fact, my memory was partially right.  We *are* already rejecting the partial application case:
> 
>   5> var b = Bar()
> b: Bar = {
>   x = 0
> }
>   6> b.bar
> repl.swift:6:3: error: partial application of 'mutating' method is not allowed
> 
> so I think that we are just missing a simple case that we should be rejecting here.
> 
> -Chris
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160225/f540f3db/attachment.html>


More information about the swift-evolution mailing list