> On Jul 9, 2016, at 9:08 AM, Austin Zheng via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> On 9 Jul 2016, at 00:53, Jon Shier <j...@jonshier.com 
>> <mailto:j...@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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to