[swift-evolution] [Discussion] "with" statement/method

Thorsten Seitz tseitz42 at icloud.com
Sat Apr 23 06:28:37 CDT 2016


> Note that function like this :
> func with<T>(item:T, apply:(T)->Void) {  apply(item) }
> 
> Produces such kind of problems:
> struct A {var x = 1}
> let a1 = A() // constant
> with (a1) { $0.x = 10 } // this will be compiled without errors/warnings


This works as expected (giving a compile error for let constant):

// for value types
func with<T>(inout item: T, apply: (inout T) throws -> Void) rethrows -> Void {
    try apply(&item)
}

// for reference types (classes)
func with<T: AnyObject>(item: T, apply: (T) throws -> Void) rethrows -> T {
    try apply(item)
    return item
}

// value types

struct A { var x = 1 }

var a1 = A()
with (&a1) {
    $0.x = 10
}
print(a1) // A(x: 10)

/*
let a2 = A()
with (&a2) { // error: cannot pass immutable value as inout argument: 'a2' is a 'let' constant
    $0.x = 10
}
print(a2)
*/

// reference types (classes)

class B : CustomDebugStringConvertible {
    var y = 1
    var debugDescription: String { return "B(y: \(y))" }
}

var b1 = B()
with (b1) {
    $0.y = 11
}
print(b1) // B(y: 11)

// reference types allow this pattern (value types don't)
let b2 = with (B()) {
    $0.y = 12
}
print(b2) // B(y: 12)


-Thorsten


> Am 22.04.2016 um 09:18 schrieb Vladimir.S via swift-evolution <swift-evolution at swift.org>:
> 
> Just wanted to summarize our opinions on this suggestion that we was discussing earlier and check if someone is ready to crate an "official" proposal for this feature.
> 
> There a number of questions regarding this feature we can discuss, for example statement vs method, what could be a placeholder of target instance inside the scope($0, $, _, .., nothing etc)
> 
> The main question, *do you support that we need "with" feature in some way in Swift 3.0 out of the box* . And if so, what variant do you prefer.
> 
> * this proposal is for *explicit* "with", where it is clear what method/property belongs to the "target" instance
> * I believe that as such feature is really useful and handy, if it is explicit and if it is clearly showing in code what we are doing - we want to have this feature as part of language/standard lib rather than possibility to use some workaround to implement it
> * It is not about saving the space in code. It is about more readable and (I insist) more stable(with less errors) code. Much less possibilities for copy-paste errors. Wrong code completion suggestion(by editor) can not produce error. It is explicit and clear, it has much less noise in code.
> * Many of us already implemented and use such "with" construction in some way
> 
> There were 2 main suggestions :
> 
> 1) Introduce "with" statement that can be used in for example in such way:
> 
> // set props just after creating
> // similar to "if let.. " and "guard let.."
> with let questionLabel = UILabel() {
>  //set props of created instance here
>  // here we can have:
>  // $0.prop = value
>  // or
>  // ..prop = value
>  // or
>  // .prop = value
>  // or
>  // _.prop = value
>  // or
>  // $.prop = value
>  // or ?
> }
> // questionLabel is available here
> 
> 
> // works for structures
> with var some = SomeStruct() {
>  //...
> }
> 
> // just for some class/structure/enum
> with questionLabel {
>  // ..
> }
> 
> probably
> 
> with var src = someNamedInstance1,
>     let dst = someNamedInstance2 {
>   src.propA = dst.propB
>   dst.someMethod(src.propC)
>   src.someMehtod()
> }
> 
> or
> with someNamedInstance1, someNamedInstance2 {
>   $0.propA = $1.propB
>   $1.someMethod($0.propC)
>   $0.someMehtod()
> }
> 
> 
> 2) Introduce .with method for each(?) class/struct, so we can use out-of-box:
> 
> let questionLabel = UILabel().with {
>  //set props of created instance here
>  $0.prop = value
> }
> 
> var someStructInstance = SomeStruct().with {target in
>  target.prop = value
> }
> 
> questionLabel.with {label in
>  label.prop = value
> }
> 
> someNamedInstance1.with(someNamedInstance2) {src, dst in
>   src.propA = dst.propB
>   dst.someMethod(src.propC)
>   src.someMehtod()
> }
> 
> Note that function like this :
> func with<T>(item:T, apply:(T)->Void) {  apply(item) }
> 
> Produces such kind of problems:
> struct A {var x = 1}
> let a1 = A() // constant
> with (a1) { $0.x = 10 } // this will be compiled without errors/warnings
> 
> 
> On 13.04.2016 17:17, Radosław Pietruszewski via swift-evolution wrote:
>> It can be (more-or-less) solved in library code today:
>> 
>>    extension NSObjectProtocol {
>>        public func with(@noescape fn: Self -> Void) -> Self {
>>            fn(self)
>>            return self
>>        }
>>    }
>> 
>> 
>> This way, you can do, on NSObjects:
>> 
>>    textLabel.with {
>> 
>>    $0.textAlignment = .Left
>> 
>>    $0.textColor = .darkTextColor()
>> 
>>    }
>> 
>> 
>> I love this pattern.
>> 
>> You can also make it a function to make it work with any value of any kind
>> (it will then take form of `with(foo) { …}`).
>> 
>> Ideally, if you could write a universal extension (something like
>> `extension Any`), you could just add this behavior, with method syntax, to
>> everything.
>> 
>> — Radek
>> 
>>> On 13 Apr 2016, at 15:15, 李海珍 via swift-evolution
>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> I recently learned some VBA and I found a very conveniently `with` statement.
>>> 
>>> `with` statement can be helpful to set property for UIKit instance.
>>> 
>>> for instance a UILabel instance `textLabel` ,with `with` statement we can
>>> set UILabel property like this
>>> 
>>> 
>>> ```swift
>>> 
>>> with textLabel{
>>> 
>>> .textAlignment= .Left
>>> 
>>> .textColor= UIColor.darkTextColor()
>>> 
>>> .font= UIFont.systemFontOfSize(15)
>>> 
>>> }
>>> 
>>> ```
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> _______________________________________________
> 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/20160423/fc7d0dba/attachment.html>


More information about the swift-evolution mailing list