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

Vladimir.S svabox at gmail.com
Mon Apr 25 08:42:58 CDT 2016


@Thorsten, thank you for providing these functions and sample code.
Unfortunately personally I can't check them now to find out if there is 
some problems with them. (But will check later)

In any case. Let's assume these functions are 100% fine and can be used in 
almost any situation with no drawbacks.

Do you(and all other) agree that such functions should be a part of 
standard library, so we'll have this "with" feature out-of-box with correct 
implementation (and so there will be no need to re-invent them for many of 
us and to re-copy into each project) ?

This is the main first question regarding this proposal.

On 23.04.2016 14:28, Thorsten Seitz wrote:
>> 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
> funcwith<T>(inoutitem: T, apply: (inoutT) throws-> Void) rethrows-> Void{
>     tryapply(&item)
> }
>
> // for reference types (classes)
> funcwith<T: AnyObject>(item: T, apply: (T) throws-> Void) rethrows-> T{
>     tryapply(item)
>     returnitem
> }
>
> // value types
>
> structA { varx = 1}
>
> vara1 = 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)
>
> classB : CustomDebugStringConvertible{
>     vary = 1
>     vardebugDescription: String{ return"B(y: \(y))"}
> }
>
> varb1 = B()
> with(b1) {
>     $0.y= 11
> }
> print(b1) // B(y: 11)
>
> // reference types allow this pattern (value types don't)
> letb2 = 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 <mailto: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>
>>>> <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>
>>>> <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>>
>>> _______________________________________________
>>> 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 <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>


More information about the swift-evolution mailing list