Over the past couple of days, the Twitters have discovered some work I'd done 
on closure-based setup. 
It's clear that a demand is out there and strong for this kind of behavior, 
even without implicit `self` as 
part of the mix or cascading. In that light, I've put together the following:

https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae>

If the community demand is this high, I think we should re-consider pushing it 
before 3. 
Feedback as always welcome, including criticism.

-- E

Introducing with to the Standard Library

Proposal: TBD
Author: Erica Sadun <https://github.com/erica>
Status: TBD
Review manager: TBD
 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae#introduction>Introduction

This proposal introduces a with function to the standard library to simplify 
the initialization and modification of constants and Foundation-sourced complex 
objects.

Swift-evolution thread: What about a VBA style with Statement? 
<http://thread.gmane.org/gmane.comp.lang.swift.evolution/14384>
 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae#motivation>Motivation

Closure-based initialization enables clean and highly directed set-up in Swift 
code. Numerous variations on the theme have been introduced on the Swift 
Evolution list and in third party github repositories. Although you can build 
solutions natively without functions, current Swift technology has drawbacks:

let questionLabel: UILabel = {
    $0.textAlignment = .Center
    $0.font =  UIFont(name:"DnealianManuscript", size: 72)
    $0.text = questionText
    $0.numberOfLines = 0
    return $0
}(UILabel())

let mySwitch : UISwitch = {
    view.addSubview($0)
    CenterViewInSuperview($0, horizontal: true, vertical: true)
    $0.addTarget(self, action: "action", forControlEvents: .TouchUpInside)
    return $0
}(UISwitch())
Assignment must be explicitly typed.
The source item must be postpended to the set-up closure.
The closure must return the item.
This approach is better suited to setting up Foundation objects than modifying 
Swift constants. When duplicating and modifying a constant, the closure must 
create a var copy and modify that copy.
While the implementation is imperfect, the wins are notable. Code naturally 
groups into a clear set-up sequence. The scoped setup avoids clumpy redundant 
lines where the same variable is accessed over and over. 

let questionLabel = UILabel()
questionLabel.textAlignment = .Center
questionLabel.font =  UIFont(name:"DnealianManuscript", size: 72)
questionLabel.text = questionText
questionLabel.numberOfLines = 0
In the case of non-reference types, a constant's fields may be set-up 
sequentially without forcing the constant to be a variable.

 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae#detailed-design>Detailed
 Design

This proposal introduces a with function that enables modification and use of 
an instance using positional references. It's not quite as clean as a solution 
with implicit self but it offers sufficient utility that a vast swath of Swift 
developers have adopted this function in some form or another.

@discardableResult
public func with<T>(_ item: T, update: @noescape (inout T) throws -> Void) 
rethrows -> T {
    var this = item; try update(&this); return this
}
In use:

struct Person { var name: String, favoriteColor: UIColor }
let john = Person(name: "John", favoriteColor: .blueColor())
let jane = with(john){ $0.name = "Jane" }
print(jane) // Person(name: "Jane", favoriteColor: UIDeviceRGBColorSpace 0 0 1 
1)

struct Point { var (x, y) : (Double, Double) }
let p1 = Point(x: 2, y: 3)
let p2 = with(p1){ $0.y = 4 }
print(p1, p2) // Point(x: 2.0, y: 3.0) Point(x: 2.0, y: 4.0)
 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae#impact-on-existing-code>Impact
 on Existing Code

This proposal is purely additive and has no impact on existing code

 
<https://gist.github.com/erica/96d9c5bb4eaa3ed3b2ff82dc35aa8dae#alternatives-considered>Alternatives
 Considered

Not adopting this proposal
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to