What about a VBA style with Statement?


(李海珍) #1

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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}


Does this have a real world use?
(Radek Pietruszewski) #2

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@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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #3

I like this idea.

In Delphi(Pascal) there is also such construction
with someVar do
  begin
  end;
And it is very handy and is used a lot (usually if you need to set/read a lot of properties of some object).

Additionally, I believe such construction prevents some possible mistakes with used variable name, especially if there is a similar-named variables in cod (sometimes because of code completion feature in editor) ex:
someVar1 = ...
someVar1....

someVar2 = ..
someVar2....
someVar1... << mistake
someVar2...

and if "with" construction were here:

with someVar2 {
   .some...
   var a = .another
   etc
}

But the problem with "with" in Delphi is that it is not explicit what method/property belongs to that someVar and what doesn't belong.
In Swift, such construction should force us to somehow be explicit regarding what methods/props belongs to that someVar instance. Seems like "dot" syntax looks OK.

Don't know if that could be implemented in Swift technically.

···

On 13.04.2016 16:15, 李海珍 via swift-evolution 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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Erica Sadun) #4

My current version is this:

func with<T>(item: T, @noescape update: (inout T) -> Void) -> T {
    var this = item; update(&this); return this
}

Used, for example:

struct Foo { var (a, b, c) = ("a", "b", "c") }
class Bar: DefaultReflectable { var (a, b, c) = ("a", "b", 2.5) }
var f = with(Foo()) { $0.a = "X" }
var b = with(Bar()) { $0.a = "X" }
print(f) // Foo(a: "X", b: "b", c: "c")
print(b) // Bar(a=X, b=b, c=c)

Is there an advantage to having a pair of functions?

-- E, who moved this to Swift-Users

···

On Apr 13, 2016, at 8:25 AM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean


(Sean Heber) #5

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

···

On Apr 13, 2016, at 9:17 AM, Radosław Pietruszewski via swift-evolution <swift-evolution@swift.org> 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@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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Erica Sadun) #6

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

My current version is this:

func with<T>(item: T, @noescape update: (inout T) -> Void) -> T {
   var this = item; update(&this); return this
}

Used, for example:

struct Foo { var (a, b, c) = ("a", "b", "c") }
class Bar: DefaultReflectable { var (a, b, c) = ("a", "b", 2.5) }
var f = with(Foo()) { $0.a = "X" }
var b = with(Bar()) { $0.a = "X" }
print(f) // Foo(a: "X", b: "b", c: "c")
print(b) // Bar(a=X, b=b, c=c)

Is there an advantage to having a pair of functions?

I don’t know if it’s a huge advantage or not, but with warnings on unused results, using a with() that has a return with a class instance would mean you’d have to discard the return result explicitly or pointlessly reassign the results to your instance (thus meaning not using a let) just to avoid the warning. If you annotated the with() to allow discarding the result, then it’d be error-prone for structs. It seemed “safer” to me to have a pair.

l8r
Sean

If you want to call

let f = with(Foo()) { $0.a = "X" }
let b = with(Bar()) { $0.a = "X" }

with constant assignment and an initializer, I'm not sure how yours would work. Could they?

-- E, trying right now in the playground

···

On Apr 13, 2016, at 9:26 AM, Sean Heber <sean@fifthace.com> wrote:

On Apr 13, 2016, at 10:08 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 13, 2016, at 8:25 AM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:


(Sean Heber) #7

I don’t know if it’s a huge advantage or not, but with warnings on unused results, using a with() that has a return with a class instance would mean you’d have to discard the return result explicitly or pointlessly reassign the results to your instance (thus meaning not using a let) just to avoid the warning. If you annotated the with() to allow discarding the result, then it’d be error-prone for structs. It seemed “safer” to me to have a pair.

l8r
Sean

···

On Apr 13, 2016, at 10:08 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 13, 2016, at 8:25 AM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

My current version is this:

func with<T>(item: T, @noescape update: (inout T) -> Void) -> T {
    var this = item; update(&this); return this
}

Used, for example:

struct Foo { var (a, b, c) = ("a", "b", "c") }
class Bar: DefaultReflectable { var (a, b, c) = ("a", "b", 2.5) }
var f = with(Foo()) { $0.a = "X" }
var b = with(Bar()) { $0.a = "X" }
print(f) // Foo(a: "X", b: "b", c: "c")
print(b) // Bar(a=X, b=b, c=c)

Is there an advantage to having a pair of functions?


(Taras Zakharko) #8

We had this kind of proposal earlier, didn’t seem to be very well received. I still think it would be a useful thing, but I’d do it as a statement (extension of do) that introduces new lexical scope (similar to self)

— Taras

···

On 13 Apr 2016, at 16:25, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

On Apr 13, 2016, at 9:17 AM, Radosław Pietruszewski via swift-evolution <swift-evolution@swift.org> 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@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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #9

Than you for sharing this method. So, do you suggest to not have this "with" construction in Swift just because we *can* implement the same behavior by using some workarounds/hacks?

I.e. do you support this proposal or don't?
Do you agree that such built-in feature will be very useful and make our programming live a little better/easier?

I strongly believe that if such feature is really useful and handy, if it is explicit and if it is clearly showing in code what we are doing - we most likely want to have this feature as part of language rather than possibility to use some workaround to implement it.

With your suggestion, how to deal with two separate classes that have no common protocol? I.e.
class A { .. }; class B {..};
Should we conform them to some protocol or create extension of each just to have this "with" feature? Don't think so.

···

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@swift.org <mailto:swift-evolution@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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #10

Yes, it really looks like language construction, and I like this approach.
with (some) {
   $0... = ...
}

But should many of us copy-paste these functions in each module/project or this is very handful feature that we want to have in our language? What do you think about the proposal?

Actually I think it is even OK if such functions will be in standard lib, i.e. without intruducing new language construct, and we can use them out-of-box to have 'with' functionality.

···

On 13.04.2016 17:25, Sean Heber via swift-evolution wrote:

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

On Apr 13, 2016, at 9:17 AM, Radosław Pietruszewski via swift-evolution <swift-evolution@swift.org> 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@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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #11

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@swift.org <mailto:swift-evolution@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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Radek Pietruszewski) #12

Than you for sharing this method. So, do you suggest to not have this "with" construction in Swift just because we *can* implement the same behavior by using some workarounds/hacks?

I.e. do you support this proposal or don't?
Do you agree that such built-in feature will be very useful and make our programming live a little better/easier?

I’m -1, at least in the foreseeable future. I do agree that this is a useful construct, but if I can do it in library code, paying only a small price for this, I’d prefer Swift to grow better in places that a library *can’t* fix.

I strongly believe that if such feature is really useful and handy, if it is explicit and if it is clearly showing in code what we are doing - we most likely want to have this feature as part of language rather than possibility to use some workaround to implement it.

With your suggestion, how to deal with two separate classes that have no common protocol? I.e.
class A { .. }; class B {..};
Should we conform them to some protocol or create extension of each just to have this "with" feature? Don't think so.

No — for now, it’s best to use a free function for now. And, like I mentioned, universal conformances could allow this to be easily added to all types — and so I’d focus on pushing *that* proposal.

···

On 13 Apr 2016, at 16:47, Vladimir.S <svabox@gmail.com> wrote:

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@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #13

+1 on statement vs lexical scope. additionally { $0.something ... } is more explicit than just .something.

···

On 13.04.2016 17:36, Taras Zakharko via swift-evolution wrote:

We had this kind of proposal earlier, didn’t seem to be very well received. I still think it would be a useful thing, but I’d do it as a statement (extension of do) that introduces new lexical scope (similar to self)

— Taras

On 13 Apr 2016, at 16:25, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

This pair works pretty well, too, if you don’t mind free functions:

func with<T>(inout this: T, @noescape using: inout T->Void) { using(&this) }
func with<T>(this: T, @noescape using: T->Void) { using(this) }

It works either with classes or mutable structs if you call it correctly and the type doesn’t matter.

l8r
Sean

On Apr 13, 2016, at 9:17 AM, Radosław Pietruszewski via swift-evolution <swift-evolution@swift.org> 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@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


with textLabel{

.textAlignment = .Left

.textColor = UIColor.darkTextColor()

.font = UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #14

I’m -1, at least in the foreseeable future. I do agree that this is a
useful construct, but if I can do it in library code, paying only a small
price for this, I’d prefer Swift to grow better in places that a library
*can’t* fix.

Well, there a lot of things that *your personal* library can fix for you.
Should we stop improve the language and start to write just personal libs with improvements?
This proposals about the feature that makes Swift better, more enjoyable to work with.

Btw, this "with" method you suggest is not replacement for language construction - it allows compilation when struct instance constant (let s = SomeStruct()) is changed inside block. Do you like this? Do you want to produce such an non-safe code to your projects?

No — for now, it’s best to use a free function for now. And, like I

No, not best, even not OK. Described above.

mentioned, universal conformances could allow this to be easily added to
all types — and so I’d focus on pushing *that* proposal.

As I understand, such a method will have the same problem with un-safe behavior in case of constant.

···

On 13.04.2016 18:09, Radosław Pietruszewski wrote:


(Patrick Smith) #15

I was wondering if all mutating and setters of a method could become a type (Typename.Mutation), say something similar to an enum.
You’d use it like this:
let alice = john mutating [ .firstName = "Alice", .makeScottishClan]
See more here:https://gist.github.com/BurntCaramel/ba2ce9dfd49595dacce07394de579172
Patrick

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(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 Fri, Apr 22, 2016 at 12:18 AM -0700, "Vladimir.S via swift-evolution" <swift-evolution@swift.org> wrote:

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 >> > 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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #16

Personally, I don't feel like your suggestion is a replacement for "with" feature. "With" not just about mutating(it can be used to just get multiply props from "target" instance), it allows to call methods of instance, use a label of "target" instance (like $0) to be used as argument (like with someInstance { ...; callFunc($0); } etc.

Also, in your suggestion there is implicit "self" for the target instance (.firstName) and this will produce not obvious code (like .someColor = .colorRed - first belongs to target instance, second - enum value)

I believe you can start new [Discussion]/[Idea] about this "mutating" feature, in this thread I'd like to collect opinions regarding the "with" feature proposal.

···

On 22.04.2016 11:12, Patrick Smith wrote:

I was wondering if all mutating and setters of a method could become a type
(Typename.Mutation), say something similar to an enum.

You’d use it like this:

let alice = john mutating [
  .firstName = "Alice",
  .makeScottishClan
]

See more here:
https://gist.github.com/BurntCaramel/ba2ce9dfd49595dacce07394de579172

Patrick

On Fri, Apr 22, 2016 at 12:18 AM -0700, "Vladimir.S via swift-evolution" > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    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(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 > >> > 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@swift.org
    >> https://lists.swift.org/mailman/listinfo/swift-evolution
    >
    > _______________________________________________
    > swift-evolution mailing list
    > swift-evolution@swift.org
    > https://lists.swift.org/mailman/listinfo/swift-evolution
    >
    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org
    https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #17

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@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@swift.org <mailto:swift-evolution@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


with textLabel{

.textAlignment= .Left

.textColor= UIColor.darkTextColor()

.font= UIFont.systemFontOfSize(15)

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Kurt Werle) #18

I've always thought that the with construct is not a good idea. It seems
to me that the moment you want to use with it indicates that you are
getting too much into some other classes business; shouldn't that class
deal with this? Why are you exposing/integrating so much of some other
class's logic? Maybe there should be a method that does all this, or maybe
a custom struct that passes all the appropriate information...

Yeah, there are exceptions - always. But for the most part I'm not a fan.

Kurt

···

--
kurt@CircleW.org
http://www.CircleW.org/kurt/


(Erica Sadun) #19

The biggest advantage of the with pattern IMO is Cocoa initializers. It provides a more unified
initialization scope. Instead of:

let questionLabel = UILabel()
questionLabel.textAlignment = .Center
questionLabel.font = UIFont(name:"DnealianManuscript", size: 72)
questionLabel.text = currentQuestion.text
questionLabel.numberOfLines = 0

You get:

let questionLabel2 = with(UILabel()) {
    $0.textAlignment = .Center
    $0.font = UIFont(name:"DnealianManuscript", size: 72)
    $0.text = currentQuestion.text
    $0.numberOfLines = 0
}

You also have the option to customize a Value type before assigning it to a constant or to base
a new value constant on a copy of an existing value constant:

struct Foo { var (a, b, c) = ("a", "b", "c") }
var f = with(Foo()) { $0.a = "X" }
print(f) // Foo(a: "X", b: "b", c: "c")

I personally would love to see a Swift construct that created a scope with `self` defined so the
awkward `$0.` prefixes could be discarded.

-- E, who may have brought up this topic once or twice before on this list

···

On Apr 13, 2016, at 9:34 AM, Kurt Werle via swift-evolution <swift-evolution@swift.org> wrote:

I've always thought that the with construct is not a good idea. It seems to me that the moment you want to use with it indicates that you are getting too much into some other classes business; shouldn't that class deal with this? Why are you exposing/integrating so much of some other class's logic? Maybe there should be a method that does all this, or maybe a custom struct that passes all the appropriate information...

Yeah, there are exceptions - always. But for the most part I'm not a fan.

Kurt


(Taras Zakharko) #20

Because many APIs use configuration/partial initialisation patterns. Look at Metal for example. But I agree that most of the time, its not such a big deal.

— Taras

···

On 13 Apr 2016, at 17:34, Kurt Werle <kurt@circlew.org> wrote:

I've always thought that the with construct is not a good idea. It seems to me that the moment you want to use with it indicates that you are getting too much into some other classes business; shouldn't that class deal with this? Why are you exposing/integrating so much of some other class's logic? Maybe there should be a method that does all this, or maybe a custom struct that passes all the appropriate information...

Yeah, there are exceptions - always. But for the most part I'm not a fan.

Kurt
--
kurt@CircleW.org
http://www.CircleW.org/kurt/ <http://www.circlew.org/kurt/>