[swift-evolution] Stdlib closure argument labels and parameter names

Erica Sadun erica at ericasadun.com
Mon Jun 27 10:58:45 CDT 2016


> On Jun 27, 2016, at 7:05 AM, Dave Abrahams <dabrahams at apple.com> wrote:
>> for i in map { ... } { // will not compile
>>    ... 
>> }
> 
> I don't think Swift wants to buy into the idea that using map without
> trailing closures is a bad habit.  We strongly believe in trailing
> closure syntax.

I strongly believe that trailing closure syntax isn't always the right thing. For example, 
many APIs, specifically those sourced from Cocoa, shouldn't use trailing closures for 
"completion", "on error" handlers, etc.

// Should use argument label. Clear, easy to distinguish
UIView.animate(
    withDuration: 0.5,
    delay: 0.0,
    options: [.curveEaseOut],
    animations: {
        
        //...
        
    },
    completion: {
        
        _ in print("done animating")

    }
)

// Shouldn't use trailing closure syntax. The call look like 
// it's "running" the completion block. 
//
UIView.animate(
    withDuration: 0.5,
    delay: 0.0,
    options: [.curveEaseOut],
    animations: {
        
        // ...
        
}) {
    
    _ in print("done animating")
    
}

Compare with:

// Should. Elegant, simple.
DispatchQueue.main.after(when: .now() + 1.0) {

    print("complete")
    PlaygroundPage.finishExecution(PlaygroundPage.current)

}

// Slightly less good
DispatchQueue.main.after(when: .now() + 1.0, execute: {

    print("complete")
    PlaygroundPage.finishExecution(PlaygroundPage.current)

})

> Why not make the argument that it's a bad habit to call map without
> *surrounding* parentheses?

It's a fair question and as I have readily admitted, a highly stylized personal choice.
Using my style is a choice that has measurable benefits and limited impact. It fixes a real 
(not theoretical) problem, is never harmful to code and when adhered to consistently
clarifies intent at the point of use, especially when expanded to functional calls that
aren't pre-built into the language -- so readers may not know at a glance what they're 
looking at as they would with `map`, `flatMap`, `filter`, and whatever sort is being called
this week.

> I disagree about readability.  One set of surrounding parentheses is
> clearer
> 
>     for var i in (x.flatMap{ Int($0) }.filter{ $0 < 10 }) {
> 

chacun à son goût. see above.

> Further, I am concerned about pervasive inefficiency when people try to
> pack this kind of chaining into a for loop with as few characters as
> possible.  Generally speaking, it would be better to do it lazily.

Yeah, kicking myself over that. Can't Swift remind me to add `lazy` 
by emitting a warning or something? I keep assuming certain things are
naturally lazy and then have to go back and de-eagerize.

>> Enhanced readability from explicit coding intent. Trailing closures 
>> *look* like a scope created by a native construct. Those enclosed in 
>> parens *look* like arguments.
> 
> I understand what you're saying, but I think it's unnecessarily fussy
> ;-)
> 
> two-can-play-at-that-game-ly y'rs,

A hit, a very palpable hit.

-- E

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


More information about the swift-evolution mailing list