Spread Operator as Shorthand for Map

As a Groovy user, I really enjoy the shorthand Spread Operator over the Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge", model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

The other distinction in Groovy is that the Spread Operator is null safe, meaning it won’t throw a NPE if an element is null, whereas the Collect Closure would. So in Swift, I would propose the Spread Operator implicitly does this when operating on an array of Optionals:

let makes = cars.map() { $0?.make }

Thanks!
Sean

You can already define an infix operator that does this. Are you proposing one be in the standard library? I would be opposed to adding new syntax for this.

···

On Dec 16, 2015, at 6:47 AM, Sean Kosanovich via swift-evolution <swift-evolution@swift.org> wrote:

As a Groovy user, I really enjoy the shorthand Spread Operator over the Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge", model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

The other distinction in Groovy is that the Spread Operator is null safe, meaning it won’t throw a NPE if an element is null, whereas the Collect Closure would. So in Swift, I would propose the Spread Operator implicitly does this when operating on an array of Optionals:

let makes = cars.map() { $0?.make }

Thanks!
Sean

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

I think there is a tension in Swift between its object oriented nature and higher-order functions which leads to a lot of repetition of { $0.property }

In this example:
cars.map { $0.make }

I’d like to write the following, but ‘make’ is a member, not a free function:
cars.map(make)

Is anyone else irked by the preponderance of { $0.property } in Swift (or is it just me being grumpy)? Not sure what the solution would be, but I can’t say I’m keen on the suggestion of:

cars*.make

It’s too mysterious.

···

On 16 Dec 2015, at 12:47, Sean Kosanovich via swift-evolution <swift-evolution@swift.org> wrote:

As a Groovy user, I really enjoy the shorthand Spread Operator over the Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge", model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

That's a pretty nifty shorthand, although I don't personally think it adds
enough on top of map to be worthwhile:

let makes = cars*.make
let makes = cars.map{$0.make}

My reasons:
* It adds new things to learn, and only saves 4 characters on map
* Perhaps I'm missing your point, but your code example is also null safe,
this doesn't seem to add an advantage.

···

On Wed, Dec 16, 2015 at 11:47 PM, Sean Kosanovich via swift-evolution < swift-evolution@swift.org> wrote:

As a Groovy user, I really enjoy the shorthand Spread Operator over the
Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge",
model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

The other distinction in Groovy is that the Spread Operator is null safe,
meaning it won’t throw a NPE if an element is null, whereas the Collect
Closure would. So in Swift, I would propose the Spread Operator implicitly
does this when operating on an array of Optionals:

let makes = cars.map() { $0?.make }

Thanks!
Sean

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

This last alternative looks a lot like a special (single expression) case of the Method Cascading proposal <https://bugs.swift.org/browse/SR-160&gt;\. If you want to go forward with this shorthand, I’d suggest adding it to method cascading as a rule: Invoking a closure with a single anonymous argument also implicitly begins a cascade with $0 as the default receiver.

  - Greg

···

On Dec 16, 2015, at 8:18 AM, Stephen Celis via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, Dec 16, 2015 at 10:50 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

If we peel off just the contextual shorthand aspect of this proposal you could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce ambiguity or cause other significant challenges in implementation).

The above creates ambiguity if there were a `map` function that takes a type with a static member `make`.

Alternatively:

    cars.map{.make}

Both create an additional meaning for dot abbreviation, though, which is confusing. I think I'm "-1" on this proposal as is. The existing form is clearer and relatively short as is.

I’d like to write the following, but ‘make’ is a member, not a free function:
cars.map(make)

If we peel off just the contextual shorthand aspect of this proposal you could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce ambiguity or cause other significant challenges in implementation).

Yes, I am proposing this be part of the standard library.

Additional use cases that are possible in Groovy are using it for setting variables or calling methods, like the following (ignore the example of changing a car’s make doesn’t make much since):

cars*.make = “Chevrolet”

or

cars*.notifyOfLowFuel()

···

On Dec 16, 2015, at 10:14 AM, Matthew Johnson <matthew@anandabits.com> wrote:

You can already define an infix operator that does this. Are you proposing one be in the standard library? I would be opposed to adding new syntax for this.

On Dec 16, 2015, at 6:47 AM, Sean Kosanovich via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

As a Groovy user, I really enjoy the shorthand Spread Operator over the Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge", model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

The other distinction in Groovy is that the Spread Operator is null safe, meaning it won’t throw a NPE if an element is null, whereas the Collect Closure would. So in Swift, I would propose the Spread Operator implicitly does this when operating on an array of Optionals:

let makes = cars.map() { $0?.make }

Thanks!
Sean

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

I’m not a macro expert, but I suspect that once there’s a macro system this sort of thing would be pretty easy to construct - possibly with something like:

macro using(x) { $0.x }
cars.map using(make)

I’d like this sort of thing to be possible, too, but I’m not sure it needs to be explicitly added to the language if a macro system is (eventually) coming.

l8r
Sean

···

On Dec 16, 2015, at 9:50 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

I’d like to write the following, but ‘make’ is a member, not a free function:
cars.map(make)

If we peel off just the contextual shorthand aspect of this proposal you could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce ambiguity or cause other significant challenges in implementation).

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

This wouldn’t be ambiguous with static methods. Confusing to some developers possibly, but not ambiguous. Map would be expecting a function that takes an instance. Depending on the details of how it was defined in the language it could be ambiguous with a static property of a function type:

Car {
  static let make: Car -> SomeOtherType
}

This potential ambiguity could probably be defined away by making the shorthand specifically apply to instance methods or something like that.

There would not be an entirely new meaning for the . shorthand. It would be an extrapolation of the shorthand for enum cases.

That said, I was replying quickly and my example was not quite accurate. “make" is a getter which cannot be accessed in unbound form today. There are proposals to allow this to be done in other threads. Syntax from one example is Car.make#get (lets not get caught up on syntax of that here). So correcting my example it would look like:

cars.map(.make#get)

If make was a method we would need to bind all of the arguments except the curried instance argument so it would look like this:

cars.map(.make())

And a method with more arguments would look like this:

cars.map(.methodWithInt(1, string: “hello"))

I’m not necessarily advocating for something like this, just trying to think through the implications of it at this point.

Matthew

···

On Dec 16, 2015, at 10:18 AM, Stephen Celis <stephen.celis@gmail.com> wrote:

On Wed, Dec 16, 2015 at 10:50 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

If we peel off just the contextual shorthand aspect of this proposal you could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce ambiguity or cause other significant challenges in implementation).

The above creates ambiguity if there were a `map` function that takes a type with a static member `make`.

Alternatively:

    cars.map{.make}

Both create an additional meaning for dot abbreviation, though, which is confusing. I think I'm "-1" on this proposal as is. The existing form is clearer and relatively short as is.

Stephen

If we peel off just the contextual shorthand aspect of this proposal you

could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce
ambiguity or cause other significant challenges in implementation).

The above creates ambiguity if there were a `map` function that takes a
type with a static member `make`.

Alternatively:

    cars.map{.make}

Both create an additional meaning for dot abbreviation, though, which is
confusing. I think I'm "-1" on this proposal as is. The existing form is
clearer and relatively short as is.

Stephen

···

On Wed, Dec 16, 2015 at 10:50 AM, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

    cars.map{.make}

This last alternative looks a lot like a special (single expression) case of the Method Cascading proposal <https://bugs.swift.org/browse/SR-160&gt;\. If you want to go forward with this shorthand, I’d suggest adding it to method cascading as a rule: Invoking a closure with a single anonymous argument also implicitly begins a cascade with $0 as the default receiver.

Thanks for bringing this up! It is not a special case of that specific proposal but it is a special case of a variation of the proposal that was discussed. Seeing it applied in this context is really interesting.

Joe Groff noted syntactic ambiguity caused by omitting $0. Unless that potential ambiguity could be resolved in some way this wouldn’t actually work. It does work if you include $0:

cars.map{$0.make}

This wouldn’t be ambiguous with static methods. Confusing to some
developers possibly, but not ambiguous. Map would be expecting a function
that takes an instance. Depending on the details of how it was defined in
the language it could be ambiguous with a static property of a function
type:

Sorry, I meant ambiguous via extension (on a sequence type). Super
contrived example:

    struct Foo {
        static var bar = Foo()
    }
    extension Array {
        func map(foo: Foo) {}
    }
    [1, 2, 3].map(.bar)

I doubt there would be much ambiguity in practice, as disambiguation would
come naturally at the call site.

There would not be an entirely new meaning for the . shorthand. It would

be an extrapolation of the shorthand for enum cases.

I merely meant that dot-abbreviation now specifically resolves to a static
member that returns the type. The dot-abbreviation in your examples is a
different behavior and adds a bit of complexity to learning Swift.

Stephen

···

On Wed, Dec 16, 2015 at 11:34 AM, Matthew Johnson <matthew@anandabits.com> wrote:

On Wed, Dec 16, 2015 at 11:34 AM, Matthew Johnson <matthew@anandabits.com> wrote:

This wouldn’t be ambiguous with static methods. Confusing to some
developers possibly, but not ambiguous. Map would be expecting a function
that takes an instance. Depending on the details of how it was defined in
the language it could be ambiguous with a static property of a function
type:

Car {
  static let make: Car -> SomeOtherType
}

This potential ambiguity could probably be defined away by making the
shorthand specifically apply to instance methods or something like that.

There would not be an entirely new meaning for the . shorthand. It would
be an extrapolation of the shorthand for enum cases.

That said, I was replying quickly and my example was not quite accurate.
“make" is a getter which cannot be accessed in unbound form today. There
are proposals to allow this to be done in other threads. Syntax from one
example is Car.make#get (lets not get caught up on syntax of that here).
So correcting my example it would look like:

cars.map(.make#get)

If make was a method we would need to bind all of the arguments except the
curried instance argument so it would look like this:

cars.map(.make())

And a method with more arguments would look like this:

cars.map(.methodWithInt(1, string: “hello"))

I’m not necessarily advocating for something like this, just trying to
think through the implications of it at this point.

Matthew

On Dec 16, 2015, at 10:18 AM, Stephen Celis <stephen.celis@gmail.com> > wrote:

On Wed, Dec 16, 2015 at 10:50 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

If we peel off just the contextual shorthand aspect of this proposal you

could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce
ambiguity or cause other significant challenges in implementation).

The above creates ambiguity if there were a `map` function that takes a
type with a static member `make`.

Alternatively:

    cars.map{.make}

Both create an additional meaning for dot abbreviation, though, which is
confusing. I think I'm "-1" on this proposal as is. The existing form is
clearer and relatively short as is.

Stephen

Sorry, I meant ambiguous via extension (on a sequence type). Super contrived example:

    struct Foo {
        static var bar = Foo()
    }
    extension Array {
        func map(foo: Foo) {}
    }
    [1, 2, 3].map(.bar)

I doubt there would be much ambiguity in practice, as disambiguation would come naturally at the call site.

There would not be an entirely new meaning for the . shorthand. It would be an extrapolation of the shorthand for enum cases.

I merely meant that dot-abbreviation now specifically resolves to a static member that returns the type. The dot-abbreviation in your examples is a different behavior and adds a bit of complexity to learning Swift.

This is still not correct for a couple of reasons. The meaning of the dot-abbreviation could be defined in several ways. A static member returning the type is not one of them. In the context of the current map example the type returned by the dot-abbreviation expression would be ‘Element -> OtherType’. (Element being the type contained in the array, which would be Self in the context of that type)

Here are some examples:

struct Foo {
    var bar: Foo

    func bar() -> OtherType
    func bar(s: String) -> OtherType

    // the property shadows the static function when accessed with Foo.bar syntax
    // the same behavior would be exhibited in the shorthand if it applied to static members
    static func bar(f: Foo) -> OtherType {}
    static var bar: Foo -> OtherType = { _ in OtherType() }
}

[Foo]().map(.bar()) // instance method
[Foo]().map(.bar(“hello")) // instance method
[Foo]().map(.bar#get) // instance property

// this would reference a static property or static function if that is allowed
// however if we define the dot-abbreviation to access only unbound instance members
// this could be a shorthand for .bar#get as it would be the only unbound instance member with the correct type
[Foo]().map(.bar)

//
[Foo]().map(.bar)

If we do add a dot-abbreviation like this it would probably make sense to define it such that it only applies to curried functions where the first argument is of the type required in the context. Because curried syntax is getting dropped that would mean only unbound instance methods / properties / subscripts would be eligible. Because the dot-abbreviation would be defined as an unbound reference we probably don’t need the special syntax for getters and subscripts.

It is possible this syntax would be confusing for some developers, at least until they learn how it works. But I don’t think we’ve seen any examples of ambiguity yet (of course there may be some we just haven’t discussed yet).

There is precedent for dot-abrreviation in the language already related to enums and this definitely improves clarity and readability. I think it definitely deserves further consideration.

Matthew

I'm confused. Isn't a static member returning the type the _only_ way dot abbreviation works right right now? Please correct me with an example if I'm wrong.

I believe the dot abbreviation only works for enum cases right now. I suppose those can be viewed as static members in some sense but they really something different than that. If I am mistaken I would like to be corrected.

I think I understand your examples. They just don't work right now and behave differently than dot abbreviation currently works.

Yes, they behave somewhat differently as they are an extension of the behavior to struct and class instance members.

It is possible this syntax would be confusing for some developers, at least until they learn how it works. But I don’t think we’ve seen any examples of ambiguity yet (of course there may be some we just haven’t discussed yet).

The shadowing you propose in your example attempts to resolve the ambiguity I was referring to.

The shadowing is *current* behavior in the language. It is not something I propose.

Let's take my earlier example. It would theoretically produce ambiguity if `Int` had a `bar` method. The resolver wouldn't have enough type information to resolve things. E.g.:

    struct Foo {
        static var bar = Foo()
    }
    extension Array {
        func map(foo: Foo) {}
    }
    extension Int {
        func bar() -> String { return String(self) }
    }
    [1, 2, 3].map(.bar) // would this refer to `Foo.bar` or `Int.bar`?

This would not refer to either. It cannot refer to Foo.bar because Foo has nothing to do with the array you are mapping over. The syntax matching my example would be:

[1, 2, 3].map(.bar())

Your example would seem to prefer `Int.bar`. This kind of complexity/gotcha/learning moment is something I'd rather avoid.

There is precedent for dot-abrreviation in the language already related to enums and this definitely improves clarity and readability. I think it definitely deserves further consideration.

Enum cases are static members (e.g., `enum Foo { case Bar }` allows you to reference the `Bar` case as `Foo.Bar`, or abbreviated as `.Bar` where type `Foo` is expected). This is what I was trying to communicate before. (The same static resolution lets you pass `.redColor()` where a `UIColor` is expected.) I'm just not sure co-opting dot abbreviation to also work with instance methods is worth the added complexity.

In the enum example here you cannot refer to .Bar in an arbitrary context. It must be known by context that you are referring to a case of Foo. It appears to me like your understanding of the existing dot abbreviation for enums is not quite correct and this misunderstanding is probably contributing to your misunderstanding and confusion regarding my examples.

Matthew

This is still not correct for a couple of reasons. The meaning of the

dot-abbreviation could be defined in several ways. A static member
returning the type is not one of them. In the context of the current map
example the type returned by the dot-abbreviation expression would be
‘Element -> OtherType’. (Element being the type contained in the array,
which would be Self in the context of that type)

I'm confused. Isn't a static member returning the type the _only_ way dot
abbreviation works right right now? Please correct me with an example if
I'm wrong.

Here are some examples:

I think I understand your examples. They just don't work right now and
behave differently than dot abbreviation currently works.

It is possible this syntax would be *confusing* for some developers, at
least until they learn how it works. But I don’t think we’ve seen any
examples of ambiguity yet (of course there may be some we just haven’t
discussed yet).

The shadowing you propose in your example attempts to resolve the ambiguity
I was referring to.

Let's take my earlier example. It would theoretically produce ambiguity if
`Int` had a `bar` method. The resolver wouldn't have enough type
information to resolve things. E.g.:

    struct Foo {
        static var bar = Foo()
    }
    extension Array {
        func map(foo: Foo) {}
    }
    extension Int {
        func bar() -> String { return String(self) }
    }
    [1, 2, 3].map(.bar) // would this refer to `Foo.bar` or `Int.bar`?

Your example would seem to prefer `Int.bar`. This kind of
complexity/gotcha/learning moment is something I'd rather avoid.

There is precedent for dot-abrreviation in the language already related to

enums and this definitely improves clarity and readability. I think it
definitely deserves further consideration.

Enum cases are static members (e.g., `enum Foo { case Bar }` allows you to
reference the `Bar` case as `Foo.Bar`, or abbreviated as `.Bar` where type
`Foo` is expected). This is what I was trying to communicate before. (The
same static resolution lets you pass `.redColor()` where a `UIColor` is
expected.) I'm just not sure co-opting dot abbreviation to also work with
instance methods is worth the added complexity.

Hope I'm being clearer this time around, and let me know if I'm still not
making sense or if I'm missing anything.

Stephen

···

On Wed, Dec 16, 2015 at 1:13 PM, Matthew Johnson <matthew@anandabits.com> wrote:

I believe the dot abbreviation only works for enum cases right now.

Nope :)

I suppose those can be viewed as static members in some sense but they
really something different than that. If I am mistaken I would like to be
corrected.

I'll do my best!

It works as I was trying to describe earlier. Any static member that
returns Self. Try the following in a playground/REPL:

    struct Foo {
        static var bar: Foo {
            return Foo()
        }
        static func baz() -> Foo {
            return Foo()
        }
    }
    let bar: Foo = .bar
    let baz: Foo = .baz()

Here's a SwiftStub demonstrating the behavior:
http://swiftstub.com/579553153

Enum cases work with dot abbreviation _because_ they are static members
that return Self. Enumerations aren't special-cased for dot abbreviation.

The shadowing is *current* behavior in the language. It is not something I

propose.

Is this true? Can you provide a full example that works in the playground
and demonstrates this? The hypothetical you paste already has certain
ambiguous issues (e.g. `var foo` and `func foo()` cannot compile together
because of redefinition).

This would not refer to either. It cannot refer to Foo.bar because Foo
has nothing to do with the array you are mapping over.

The example I give works in the playground. Try it! :)

The syntax matching my example would be:

[1, 2, 3].map(.bar())

This would be ambiguous with a static function, `bar()`, that return Self.

In the enum example here you cannot refer to .Bar in an arbitrary
context. It must be known by context that you are referring to a case of
Foo. It appears to me like your understanding of the existing dot
abbreviation for enums is not quite correct and this misunderstanding is
probably contributing to your misunderstanding and confusion regarding my
examples.

I don't believe that I'm misunderstanding, but I'll take working examples
to the contrary.

Please try the examples I've provided in a playground (and the SwiftStub
link, above). I hope I've clarified how dot abbreviation works! Let me know
if you have any questions.

Stephen

···

On Wed, Dec 16, 2015 at 2:18 PM, Matthew Johnson <matthew@anandabits.com> wrote:

I think you would be able to define such an operator if .make was
recognized as Car.make in the Car context.
Which would be a cool addition to current rules.

···

On Wed, Dec 16, 2015 at 18:15 Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

You can already define an infix operator that does this. Are you
proposing one be in the standard library? I would be opposed to adding new
syntax for this.

On Dec 16, 2015, at 6:47 AM, Sean Kosanovich via swift-evolution < > swift-evolution@swift.org> wrote:

As a Groovy user, I really enjoy the shorthand Spread Operator over the
Collect Closure (Map is the equivalent in Swift).

Consider the following Swift code:

struct Car {
    let make: String
    let model: String
}

let cars = [Car(make: "Jeep", model: "Grand Cherokee"), Car(make: "Dodge",
model: "Challenger")]
let makes = cars.map() { $0.make }

Now consider the same code using a Spread Operator:

let makes = cars*.make

The other distinction in Groovy is that the Spread Operator is null safe,
meaning it won’t throw a NPE if an element is null, whereas the Collect
Closure would. So in Swift, I would propose the Spread Operator implicitly
does this when operating on an array of Optionals:

let makes = cars.map() { $0?.make }

Thanks!
Sean
_______________________________________________
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

Assuming the implementation is feasible, it looks pretty good to me.

···

On 16 Dec 2015, at 15:50, Matthew Johnson <matthew@anandabits.com> wrote:

If we peel off just the contextual shorthand aspect of this proposal you could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce ambiguity or cause other significant challenges in implementation).

Perhaps cars.map(Car.make)? We already have method references, why define a
new syntax?

···

On Wed, Dec 16, 2015, 11:18 AM Stephen Celis via swift-evolution < swift-evolution@swift.org> wrote:

On Wed, Dec 16, 2015 at 10:50 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

If we peel off just the contextual shorthand aspect of this proposal you

could write:

cars.map(.make)

That does seem like a big win if it is feasible (doesn’t introduce
ambiguity or cause other significant challenges in implementation).

The above creates ambiguity if there were a `map` function that takes a
type with a static member `make`.

Alternatively:

    cars.map{.make}

Both create an additional meaning for dot abbreviation, though, which is
confusing. I think I'm "-1" on this proposal as is. The existing form is
clearer and relatively short as is.

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

Hey, we’re back where we started! ; )

···

On 16 Dec 2015, at 17:20, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Joe Groff noted syntactic ambiguity caused by omitting $0. Unless that potential ambiguity could be resolved in some way this wouldn’t actually work. It does work if you include $0:

cars.map{$0.make}