[swift-evolution] [Accepted] SE-0111: Remove type system significance of function argument labels

David Owens II david at owensd.io
Mon Jul 11 00:30:49 CDT 2016


> On Jul 9, 2016, at 9:08 AM, Austin Zheng via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> On 9 Jul 2016, at 00:53, Jon Shier <jon at jonshier.com <mailto:jon at jonshier.com>> wrote:
>> 
>>> While I can see why removing the labels from the type system would be a good idea, I don’t see why calling the functions with labels would be actively prohibited. That’s useful information for the developer to have, and if the compiler doesn’t know them in some way, you can be assured Xcode’s autocomplete won’t see them. 
>> 
>> I wish the core team or the author of the proposal came to this thread and engaged again with the community. 
> 
> I'm not inclined to spend time engaging with people who couldn't be bothered to give feedback during the week-long official review period.

Not all people "couldn’t be bothered” but had life events, such as moving across states with four kids, that prevented them from being able to engage during the official review period. 

I’ve read through all of the posts that I see in my mailbox regarding this topic and I’ve yet to see any real answer to the concerns of tooling, typealias usage, closures, and code readability and maintainability concerns under this new proposal. This is the closest I’ve seen (from Douglas Gregor a few days ago):

> The core team’s intent is that one can add cosmetic labels to function types, but that those labels are not (cannot be) used at the call site, e.g.,

Do you have specific post in mind that addresses the these concerns? Maybe I’m just missing them, but I really don’t see those addressed and they are not mentioned in the proposal at all.

Let’s say I want to model a problem regarding some library functions that work with resizing some image type. Today, if I did that, the tooling would give me auto-completion for all of the parameter labels and the code is very legible. 

struct Size {
    var x: Int
    var y: Int
}

struct Image {
    var data: Data
    var size: Size
    // lots more properties...
}

typealias ImageResizedCallback = (original: Image, resized: Image) -> Void

func doResizeA(image: Image, completed: ImageResizedCallback) {
    let newData = image.data
    let newSize = image.size

    // do some work that's really slow...
    
    completed(original: image, resized: Image(data: newData, size: newSize))
}

func doResizeB(image: Image, completed: (original: Image, resized: Image) -> Void) {
    let newData = image.data
    let newSize = image.size

    // do some work that's really slow...
    
    completed(original: image, resized: Image(data: newData, size: newSize))
}

In either approach, `doResizeA` with a named callback or `doResizeB` with an explicit parameter type offer benefits that are lost under this proposal.

let someAsset = Image(data: Data(), size: Size(x: 100, y: 100))
    
doResizeA(image: someAsset, completed: { (original, resized) in
    print("doResizeA - original: \(original), resized: \(resized)")
})

doResizeB(image: someAsset, completed: { (original, resized) in
    print("doResizeB - original: \(original), resized: \(resized)")
})

Note that both `original` and `resized` get auto-completed for us here. This provides great code clarity and insights. This is also self-documenting code.

However, under this proposal as accepted (as I understand it), we are left with this:

func doResizeC(image: Image, completed: (Image, Image) -> Void) {
    let newData = image.data
    let newSize = image.size

    // do some work that's really slow...
    
    completed(image, Image(data: newData, size: newSize))
}

This code is no longer self-documenting. I have no idea at looking at the call signature which order the images to `completed` should be.

Further, I get no help here when trying to use it:

doResizeC(image: someAsset) { (<#Image#>, <#Image#>) in
    <#code#>
}

What do I label for the two images? This is a workflow regression. Yes, maybe the underlying model is more correct. However, this comes at a burden to actually authoring and maintaining the code. To me, that’s a truly unfortunate cost.

So now I probably write this:

doResizeC(image: someAsset) {
    print("doResizeC1 - original: \($0), resized: \($1)")
}

Or, if I happen to know or look-up the order, I can fill in the labels myself:

doResizeC(image: someAsset, completed: { (original, resized) in
    print("doResizeC2 - original: \(original), resized: \(resized)")
})

Further, we are able to turn runtime errors into compile-time checks when refactoring the signatures in the `doResizeA` and `doResizeB` functions - e.g. change the order of `original` and `resized` and you’ll get the compiler errors. This no longer happens under this proposal because the labels are erased. One way around that is to use types to solve this problem, but Swift provides no convenient way to have two `Image` types that share the same implementation but are considered as different types (sure, I could box them…).

I can get these benefits back, but now I need to introduce even more complexity into the system.

protocol ResizeCallbackType {
    func resized(original: Image, resized: Image)
}

struct ResizeCallback : ResizeCallbackType {
    func resized(original: Image, resized: Image) {
        print("resized - original: \(original), resized: \(resized)")
    }
}

func doResizeD(image: Image, callback: ResizeCallbackType) {
    let newData = image.data
    let newSize = image.size
    
    // do some work that's really slow...
    
    callback.resized(original: image, resized: Image(data: newData, size: newSize))
}

doResizeD(image: someAsset, callback: ResizeCallback())

But who really wants to go through all the protocol effort just to get back to a place being able to allow for label usage again? 

I agree that the proposal provides a “more correct” underlying model for Swift. However, before being approved, I would have really liked to have seen the above workflow and what I consider to be code readability and maintainability regressions addressed.

-David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160710/88b28286/attachment-0001.html>


More information about the swift-evolution mailing list