What about a VBA style with Statement?


(Ted van Gaalen) #1

Well, method cascading might also be
an alternative to consider?

In Smalltalk this is possible like so:

     someInstance
            eat: ‘cookie'
            print: “Hmmm, that was good!”
            beHappy
            singCookiesSong ;

In Smalltalk, the semicolon closes the method cascading
       
In Dart, method cascading goes like this:

     someInstance
            ..eat (“‘cookie”)
            ..print( “Hmmm, that was good!”)
            ..beHappy()
            ..singCookiesSong();

cascading is indicated by a .. doubleDot, preceding the method names

Why not implement this in Swift?
in that case the semicolon would not be needed.

What to do with methods (functions) that return something?
(in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is implicitly
returned in absence of a return value and can be ignored.

TedvG

···

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

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.


(Tino) #2

(in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is implicitly
returned in absence of a return value and can be ignored.

I'm a big fan of returning self — its much more useful than void…
But it seems the Swift-community doesn't like method chaining.


(Jonathan Tang) #3

I dunno about that... AlamoFire and SwiftyJSON both use it, and are quite
popular with rank-and-file Swift programmers. It's certainly not popular
in the Objective-C community (where the syntax doesn't really support it),
but it seems like the Swift community may be warming up to it.

I also like the idea of a dedicated method-cascading operator, like what
Dart has. It eliminates the need for a programmer to explicitly remember
to 'return self' at the end of a chainable method. Not sure how well it'd
integrate with SE-0047 (@discardableResult) though.

···

On Thu, Apr 14, 2016 at 8:23 AM, Tino Heth via swift-evolution < swift-evolution@swift.org> wrote:

> (in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is
implicitly
> returned in absence of a return value and can be ignored.
I'm a big fan of returning self — its much more useful than void…
But it seems the Swift-community doesn't like method chaining.


(Erica Sadun) #4

Method cascades draft: https://gist.github.com/erica/6794d48d917e2084d6ed

deferred to after 3.0

-- E

···

On Apr 14, 2016, at 10:42 AM, Jonathan Tang via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 14, 2016 at 8:23 AM, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> (in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is implicitly
> returned in absence of a return value and can be ignored.
I'm a big fan of returning self — its much more useful than void…
But it seems the Swift-community doesn't like method chaining.

I dunno about that... AlamoFire and SwiftyJSON both use it, and are quite popular with rank-and-file Swift programmers. It's certainly not popular in the Objective-C community (where the syntax doesn't really support it), but it seems like the Swift community may be warming up to it.

I also like the idea of a dedicated method-cascading operator, like what Dart has. It eliminates the need for a programmer to explicitly remember to 'return self' at the end of a chainable method. Not sure how well it'd integrate with SE-0047 (@discardableResult) though.


(Andrey Tarantsov) #5

I also like the idea of a dedicated method-cascading operator, like what Dart has. It eliminates the need for a programmer to explicitly remember to 'return self' at the end of a chainable method. Not sure how well it'd integrate with SE-0047 (@discardableResult) though.

Method cascades draft: https://gist.github.com/erica/6794d48d917e2084d6ed

deferred to after 3.0

I really think this settles the discussion, because methods cascades are *the* way to implement this kind of thing. (And for the record, I would prefer a SmallTalk/Dart-like syntax to a "with" statement.)

A


(Thorsten Seitz) #6

Returning self is not needed for method cascades in Smalltalk. Actually the return values are ignored because all methods of a cascade are sent to the same receiver. Only the last return value is used as result of the whole cascade.

The method cascade in Smalltalk is written as follows:

receive method1: x; method2: y; method3: z.

i.e. messages which ar part of the cascade are separated by ';' and the statement is finished by '.' like all statements in Smalltalk.

-Thorsten

···

Am 14.04.2016 um 17:23 schrieb Tino Heth via swift-evolution <swift-evolution@swift.org>:

(in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is implicitly
returned in absence of a return value and can be ignored.

I'm a big fan of returning self — its much more useful than void…
But it seems the Swift-community doesn't like method chaining.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #7

-1
I can't see a significant advantage over using the library based approach where the receiver is clearly recognizable and no context problems arise.

-Thorsten

···

Am 14.04.2016 um 19:03 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org>:

On Apr 14, 2016, at 10:42 AM, Jonathan Tang via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 14, 2016 at 8:23 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

> (in Smalltalk, like in Swift?, if i remember correctly, ‘self’ is implicitly
> returned in absence of a return value and can be ignored.
I'm a big fan of returning self — its much more useful than void…
But it seems the Swift-community doesn't like method chaining.

I dunno about that... AlamoFire and SwiftyJSON both use it, and are quite popular with rank-and-file Swift programmers. It's certainly not popular in the Objective-C community (where the syntax doesn't really support it), but it seems like the Swift community may be warming up to it.

I also like the idea of a dedicated method-cascading operator, like what Dart has. It eliminates the need for a programmer to explicitly remember to 'return self' at the end of a chainable method. Not sure how well it'd integrate with SE-0047 (@discardableResult) though.

Method cascades draft: https://gist.github.com/erica/6794d48d917e2084d6ed

deferred to after 3.0

-- E

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


(Erica Sadun) #8

It's been quite a while since the original discussion and I'm going to go all Brent R-G on the answer, which is I've come to prefer the Dart solution for cascading, think `with` is better suited for mutating copies of struct constants (Immutable setters <http://ericasadun.com/2016/03/24/immutable-setters/>, may not be language-inclusion suitable), and think binding self in closures is yet a third issue.

Brent, concur?

-- E

···

On Apr 14, 2016, at 12:30 PM, Andrey Tarantsov <andrey@tarantsov.com> wrote:

I also like the idea of a dedicated method-cascading operator, like what Dart has. It eliminates the need for a programmer to explicitly remember to 'return self' at the end of a chainable method. Not sure how well it'd integrate with SE-0047 (@discardableResult) though.

Method cascades draft: https://gist.github.com/erica/6794d48d917e2084d6ed

deferred to after 3.0

I really think this settles the discussion, because methods cascades are *the* way to implement this kind of thing. (And for the record, I would prefer a SmallTalk/Dart-like syntax to a "with" statement.)


(Brent Royal-Gordon) #9

I really think this settles the discussion, because methods cascades are *the* way to implement this kind of thing. (And for the record, I would prefer a SmallTalk/Dart-like syntax to a "with" statement.)

It's been quite a while since the original discussion and I'm going to go all Brent R-G on the answer, which is I've come to prefer the Dart solution for cascading, think `with` is better suited for mutating copies of struct constants (Immutable setters, may not be language-inclusion suitable), and think binding self in closures is yet a third issue.

Brent, concur?

I'm not totally sold on Dart-style method cascading (although that's partly just the `..` syntax), but if that's been deferred to after Swift 3, then we're certainly in agreement on what we want now. :^)

In terms of the `with` function, I think one version would handle both shorthanding a long variable name *and* modifying and returning a value:

  @discardableResult public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
    var copy = value
    try user(&copy)
    return copy
  }

At some point, they fixed the weird thing where you had to explicitly give the type of an inout closure parameter, so there's no syntactic penalty if you don't need to mutate. `user` could be `@noescape(once)` if that feature is ever added.

In theory, it might be nice to have two versions, one mutating and one not, simply so you don't accidentally throw away a mutation:

  public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
    var copy = value
    try user(&copy)
    return copy
  }

  public func with<T>(_ value: T, user: @noescape T throws -> Void) rethrows {
    try user(value)
  }

In practice, however, Swift (or Swift 2 at least) seems to consider this ambiguous, so we're probably out of luck there.

In terms of `self` parameters, I think the rule is simply this:

* Functions and closures (but not methods) may give a parameter the internal name `self`.
* If there is a `self` parameter, it behaves just as `self` in a method would—implicit method calls, special treatment in terms of capturing by closures, assignable only if it's `inout`, etc.
* If a closure has a `self` parameter, there is no way to access the outer scope's `self`, just like any other shadowed variable.

I would actually like to see `self` become as shadowable as any other variable, but there seems to be some resistance to that idea.

P.S. Does that mean that blithely declaring that something is actually several orthogonal features is now a Royal decree?

···

--
Brent Royal-Gordon
Architechies


(Vladimir) #10

As for methods cascades, IMO it is a good feature and I support it as addition to 'with' feature. Method cascading can't be used to set/get values of multiply props, the main purpose of 'with'

I strongly feel that functions is not a solution for 'with' feature.
Functions add additional complexity, more possibilities for problems/errors, as we are creating the bock and calling it then.
It seems like functions allows to produce code that will compile, but will raise error on execution like
struct ST {
     var x = 5
}

with (ST) { // just type here
     print($0.x)
}

and some number of similar problems. Also, why do we need parenthesis in with? Do we need them in "if"? in "for" ? in "switch"?

with s {
}

I believe "with" should be implemented as standard construction of the language. Opinions?

···

On 15.04.2016 5:12, Brent Royal-Gordon via swift-evolution wrote:

I really think this settles the discussion, because methods cascades are *the* way to implement this kind of thing. (And for the record, I would prefer a SmallTalk/Dart-like syntax to a "with" statement.)

It's been quite a while since the original discussion and I'm going to go all Brent R-G on the answer, which is I've come to prefer the Dart solution for cascading, think `with` is better suited for mutating copies of struct constants (Immutable setters, may not be language-inclusion suitable), and think binding self in closures is yet a third issue.

Brent, concur?

I'm not totally sold on Dart-style method cascading (although that's partly just the `..` syntax), but if that's been deferred to after Swift 3, then we're certainly in agreement on what we want now. :^)

In terms of the `with` function, I think one version would handle both shorthanding a long variable name *and* modifying and returning a value:

  @discardableResult public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
    var copy = value
    try user(&copy)
    return copy
  }

At some point, they fixed the weird thing where you had to explicitly give the type of an inout closure parameter, so there's no syntactic penalty if you don't need to mutate. `user` could be `@noescape(once)` if that feature is ever added.

In theory, it might be nice to have two versions, one mutating and one not, simply so you don't accidentally throw away a mutation:

  public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
    var copy = value
    try user(&copy)
    return copy
  }

  public func with<T>(_ value: T, user: @noescape T throws -> Void) rethrows {
    try user(value)
  }

In practice, however, Swift (or Swift 2 at least) seems to consider this ambiguous, so we're probably out of luck there.

In terms of `self` parameters, I think the rule is simply this:

* Functions and closures (but not methods) may give a parameter the internal name `self`.
* If there is a `self` parameter, it behaves just as `self` in a method would—implicit method calls, special treatment in terms of capturing by closures, assignable only if it's `inout`, etc.
* If a closure has a `self` parameter, there is no way to access the outer scope's `self`, just like any other shadowed variable.

I would actually like to see `self` become as shadowable as any other variable, but there seems to be some resistance to that idea.

P.S. Does that mean that blithely declaring that something is actually several orthogonal features is now a Royal decree?