[swift-evolution] [Pitch] Circling back to `with`

Jacob Bandes-Storch jtbandes at gmail.com
Wed May 25 15:48:05 CDT 2016


I like this pretty well, and I think "with()" makes sense as a peer of
"withUnsafePointer()", "withExtendedLifetime()", etc.

I'd also be okay with waiting for a comprehensive method-cascading
solution. I don't find this issue particularly urgent, because it's pretty
easily solvable with an extension or just using closures.

On Wed, May 25, 2016 at 11:28 AM, Erica Sadun via swift-evolution <
swift-evolution at swift.org> wrote:

> 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
>
> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160525/c7d69068/attachment.html>


More information about the swift-evolution mailing list