[Proposal Idea] dot shorthand for instance members


(Matthew Johnson) #1

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew


Referring to failable initializer with leading dot syntax
(Sean Kosanovich) #2

This was/is being discussed at length in this thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002742.html

···

On Dec 17, 2015, at 10:27 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Al Skipp) #3

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }

Al

···

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew


(Radek Pietruszewski) #4

Interesting! I’d definitely be for some shortcut syntax here, as this seems to be a very, very common pattern. Passing a function to, say, `map` is so much easier and cleaner than passing a method in Swift — even though Swift generally always prefers methods to functions!

I haven’t spent too much thinking this through, but I think this is sound.

For contexts where a T is expected, .foo means T.foo

But it’s not ambiguous here, because we’re expecting T -> U here, and functions can’t have static members (or any members for that matter :P). So passing a .foo could unambiguously mean T.foo(T) — an instance method on T, returning U.

I’d be for dropping the parens, they seem unnecessary, and are confusing (we’re passing a function, not calling it). It should be unambiguous with properties since methods and properties share a name space.

And, speaking of, I’d also just make it work with properties with the same syntax. So array.map(.foo) would call $0.foo() if `foo` is a method, or $0.foo if `foo` is a property.

(Am I missing something?)

— Radek

···

On 18 Dec 2015, at 04:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Rob Mayoff) #5

When you access a static member of a type using the dot shortcut, Swift
evaluates the expression immediately.

Are you proposing that when you access a member of an instance, Swift
generate a closure?

Or are you proposing that Swift generate a closure or not depending on how
the expression's value is to be used?

Either way seems inconsistent with the static member situation, and like a
potential source of confusion: not everyone uses the One True Convention™
of .Capitalized .Static .Members and .lowercase .instance .members, so one
cannot reliably deduce the outcome based on the case of the character after
the dot.

···

On Thu, Dec 17, 2015 at 9:27 PM, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())


(Kevin Lundberg) #6

Interesting proposal, but how would it work with closures that take two
or more params? What would the following expression become:

[1,2,3,4].reduce("", { $0.description + $1.description })

Is this special syntax that would only apply to closures with one
parameter? If so I'm not sure that I would consider it worth the added
complexity (though I agree that the $0 doesn't look that nice normally).

- Kevin

···

On 12/17/2015 10:27 PM, Matthew Johnson via swift-evolution wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Matthew Johnson) #7

Thanks for lining to the original thread Sean. I should have done that myself.

I started a new thread as this is really an independent feature that is related to the spread operator but stands on its own. It deserves a thread and subject line of its own.

Matthew

···

Sent from my iPad

On Dec 18, 2015, at 6:38 AM, Sean Kosanovich <sean7512@me.com> wrote:

This was/is being discussed at length in this thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002742.html

On Dec 17, 2015, at 10:27 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Matthew Johnson) #8

Thanks Al. I should have also pointed out that the syntactic advantage is a bit greater in other contexts where the braces would not replace parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that can improve clarity and readability.

Matthew

···

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }


(Sean Kosanovich) #9

Matthew,

Understood, I just wanted to link the conversations together.

As for the idea, I am a huge fan of removing the necessary $0.

-Sean

···

On Dec 18, 2015, at 7:57 AM, Matthew Johnson <matthew@anandabits.com> wrote:

Thanks for lining to the original thread Sean. I should have done that myself.

I started a new thread as this is really an independent feature that is related to the spread operator but stands on its own. It deserves a thread and subject line of its own.

Matthew

Sent from my iPad

On Dec 18, 2015, at 6:38 AM, Sean Kosanovich <sean7512@me.com <mailto:sean7512@me.com>> wrote:

This was/is being discussed at length in this thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002742.html

On Dec 17, 2015, at 10:27 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Dennis Lysenko) #10

+1. One important consideration, however, and I would love to see some
input from Chris Lattner or someone else who works on LLVM, is how much it
would complicate the grammar of the language when all possible cases are
considered.

···

On Fri, Dec 18, 2015, 8:05 AM Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in
type contexts expecting a value of the type in question. This is most
commonly used with enum cases.

Swift does not currently offer shorthand for instance members.
Introducing a shorthand for instance members would improve clarity and
readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument
function. It would allow abbreviated access to any visible instance
property getter or instance method on the type of the argument. Of course
the return type would need to match the return type expected by the context
or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The
feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like
it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m
personally in favour, but perhaps there are potential issues with the
suggestion?

It’s only a small visual change, but I think it is a syntactic
improvement. Let’s pretend for a moment that the current syntax was:
*anArray.map(.anInstanceMethod())*

I’m not sure many people would argue for it to be changed to:
*anArray.map { $0.anInstanceMethod() }*

Thanks Al. I should have also pointed out that the syntactic advantage is
a bit greater in other contexts where the braces would not replace
parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that
can improve clarity and readability.

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


(Johan K. Jensen) #11

I’m not very fond of having just a single dot in front of the method call,
as it could easily be missed.
In the case of s.predicate = .hasPrefix("abc"), I would prefer something
slightly more expressive.

As it is right now in Swift, accessing methods directly gives you a curried
function back, which expects the object instance as argument in the first
call, and the rest in the second call.
E.g. String.hasPrefix("abcd")("a") is the same as "abcd".hasPrefix("a")

Flipping the arguments like this:
func flip<A, B, C>(f: A -> B -> C) -> (B -> A -> C) {
    return { valB in
        return { valA in
            return f(valA)(valB)
        }
    }
}

String.hasPrefix("abcd")("a")
let myHasPrefix = flip(String.hasPrefix)
myHasPrefix("a")("abcd")

…would allow us to write the following:
s.predicate = flip(String.hasPrefix("abcd"))

Perhaps it could be extended to something akin to
s.predicate = String::hasPrefix("abcd")

The currying only works for methods and not for properties, so this isn’t
currently possible to express like the above:
["John", "Rachel", "Thomas"].map({ $0.endIndex })
["John", "Rachel", "Thomas"].map({ $0.characters.count })

—Johan

···

On Fri, Dec 18, 2015 at 2:05 PM, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in
type contexts expecting a value of the type in question. This is most
commonly used with enum cases.

Swift does not currently offer shorthand for instance members.
Introducing a shorthand for instance members would improve clarity and
readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument
function. It would allow abbreviated access to any visible instance
property getter or instance method on the type of the argument. Of course
the return type would need to match the return type expected by the context
or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The
feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like
it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m
personally in favour, but perhaps there are potential issues with the
suggestion?

It’s only a small visual change, but I think it is a syntactic
improvement. Let’s pretend for a moment that the current syntax was:
*anArray.map(.anInstanceMethod())*

I’m not sure many people would argue for it to be changed to:
*anArray.map { $0.anInstanceMethod() }*

Thanks Al. I should have also pointed out that the syntactic advantage is
a bit greater in other contexts where the braces would not replace
parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that
can improve clarity and readability.

Matthew

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


(Matthew Johnson) #12

Interesting! I’d definitely be for some shortcut syntax here, as this seems to be a very, very common pattern. Passing a function to, say, `map` is so much easier and cleaner than passing a method in Swift — even though Swift generally always prefers methods to functions!

I haven’t spent too much thinking this through, but I think this is sound.

For contexts where a T is expected, .foo means T.foo

But it’s not ambiguous here, because we’re expecting T -> U here, and functions can’t have static members (or any members for that matter :P). So passing a .foo could unambiguously mean T.foo(T) — an instance method on T, returning U.

I’d be for dropping the parens, they seem unnecessary, and are confusing (we’re passing a function, not calling it). It should be unambiguous with properties since methods and properties share a name space.

And, speaking of, I’d also just make it work with properties with the same syntax. So array.map(.foo) would call $0.foo() if `foo` is a method, or $0.foo if `foo` is a property.

I probably should have showed more examples in my original post.

Making this work with property getters was one of the examples I posted in the other thread:

anArray.map(.aProperty)

The reason I used parentheses in the example of a method that takes no argument is that what we’re actually doing is binding the non-self arguments. This is more clear with an example of a method that does take additional arguments:

anArray.map(.hasPrefix(“foo”))

I hadn’t tried declaring property and no argument method with the same name until you said this. You are correct that it’s unambiguous. I didn’t realize this when I first posted this idea.

If we don’t omit them it’s always clear whether we are passing a property or a method. I think requiring the parentheses is probably worth the syntactic cost. It also allows for a straightforward rewrite to a closure by wrapping the expression in braces and placing $0 prior to the dot.

···

On Dec 18, 2015, at 1:36 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

(Am I missing something?)

— Radek

On 18 Dec 2015, at 04:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Matthew Johnson) #13

When you access a static member of a type using the dot shortcut, Swift evaluates the expression immediately.

Are you proposing that when you access a member of an instance, Swift generate a closure?

Or are you proposing that Swift generate a closure or not depending on how the expression's value is to be used?

I was thinking of it more in terms of binding the non-self arguments, but either way is effectively the same. This would be necessary in all cases, although in the case of property getters and nullary methods there would no arguments to bind.

Either way seems inconsistent with the static member situation, and like a potential source of confusion: not everyone uses the One True Convention™ of .Capitalized .Static .Members and .lowercase .instance .members, so one cannot reliably deduce the outcome based on the case of the character after the dot.

You can easily deduce it by the type context which you need to know to understand the code anyway. As capitalization is not enforced by the language it is not reasonable to deduce anything based on that.

If you think it could potentially be confusing that is a reasonable position.

···

On Dec 19, 2015, at 1:37 AM, Rob Mayoff via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Dec 17, 2015 at 9:27 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Radek Pietruszewski) #14

anArray.map(.hasPrefix(“foo”))

I’m against this. Yes, it extends the functionality of the proposal even more and could allow for more closures to be rewritten in this style — but at a severe cost in clarity IMHO.

I mean, with `map(.aMethod)`, you’re passing a reference to a method available on the receiver. This is actually very similar to passing `foo(.EnumCase)`, as in both cases we’re accessing a static member of the type. (Yes, also with the former example if you consider instance methods as curried functions on the type that take self as the first parameter.) So, there’s some nice symmetry and predictability, even if the dot-syntax has more than one use.

But with `map(.hasPrefix(“foo”))`, you’re implicitly constructing a new closure, that calls a method, and passes an argument. This isn’t immediately obvious. There’s no symmetry. It looks as if I was passing the result of calling some method, and the dot at the beginning meant something else (cf the se-0009 review thread). I couldn’t figure easily figure out that this is actually implicit contents of a new closure.

The potential for confusion is great. I’m not convinced the benefit outweighs the cost here.

— Radek

···

On 19 Dec 2015, at 02:10, Matthew Johnson <matthew@anandabits.com> wrote:

On Dec 18, 2015, at 1:36 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

Interesting! I’d definitely be for some shortcut syntax here, as this seems to be a very, very common pattern. Passing a function to, say, `map` is so much easier and cleaner than passing a method in Swift — even though Swift generally always prefers methods to functions!

I haven’t spent too much thinking this through, but I think this is sound.

For contexts where a T is expected, .foo means T.foo

But it’s not ambiguous here, because we’re expecting T -> U here, and functions can’t have static members (or any members for that matter :P). So passing a .foo could unambiguously mean T.foo(T) — an instance method on T, returning U.

I’d be for dropping the parens, they seem unnecessary, and are confusing (we’re passing a function, not calling it). It should be unambiguous with properties since methods and properties share a name space.

And, speaking of, I’d also just make it work with properties with the same syntax. So array.map(.foo) would call $0.foo() if `foo` is a method, or $0.foo if `foo` is a property.

I probably should have showed more examples in my original post.

Making this work with property getters was one of the examples I posted in the other thread:

anArray.map(.aProperty)

The reason I used parentheses in the example of a method that takes no argument is that what we’re actually doing is binding the non-self arguments. This is more clear with an example of a method that does take additional arguments:

anArray.map(.hasPrefix(“foo”))

I hadn’t tried declaring property and no argument method with the same name until you said this. You are correct that it’s unambiguous. I didn’t realize this when I first posted this idea.

If we don’t omit them it’s always clear whether we are passing a property or a method. I think requiring the parentheses is probably worth the syntactic cost. It also allows for a straightforward rewrite to a closure by wrapping the expression in braces and placing $0 prior to the dot.

(Am I missing something?)

— Radek

On 18 Dec 2015, at 04:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Matthew Johnson) #15

Interesting proposal, but how would it work with closures that take two
or more params? What would the following expression become:

[1,2,3,4].reduce("", { $0.description + $1.description })

Is this special syntax that would only apply to closures with one
parameter? If so I'm not sure that I would consider it worth the added
complexity (though I agree that the $0 doesn't look that nice normally).

It wouldn’t work for two or more arguments. The point of it is to be shorthand for unbound instance members (or partially bound if we allow methods taking additional arguments), which would inherently receive a single argument - the instance.

Whether or not it is worth the cost is a fair question that needs to be answered through discussion.

I think it is worth continuing to discuss and explore because it addresses a very common use case. Many higher order functions take function arguments that receive only a single argument.

···

On Dec 20, 2015, at 1:06 AM, Kevin Lundberg via swift-evolution <swift-evolution@swift.org> wrote:

- Kevin

On 12/17/2015 10:27 PM, Matthew Johnson via swift-evolution wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

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


(Matthew Johnson) #16

+1. One important consideration, however, and I would love to see some input from Chris Lattner or someone else who works on LLVM, is how much it would complicate the grammar of the language when all possible cases are considered.

I ran this by Joe Groff on Twitter and he said it makes sense. Would be great to get a comment on the list as well.

It’s quite similar to the existing dot shorthand for static members but applies in a different typing context. I may be overlooking something but I don’t believe there would be any complications that were not addressed there.

···

On Fri, Dec 18, 2015, 8:05 AM Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm <mailto:al_skipp@fastmail.fm>> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }

Thanks Al. I should have also pointed out that the syntactic advantage is a bit greater in other contexts where the braces would not replace parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that can improve clarity and readability.

Matthew

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


(Matthew Johnson) #17

Johan, you are right that all of this is possible but it seems rather verbose to me. I’d rather use the currently possible { $0.member } syntax. The point of the idea is to remove syntactic noise.

It’s reasonable to argue that this isn’t necessary, but in that case the current state suffices IMO. We don’t need a more verbose alternative to what we already have.

···

On Dec 18, 2015, at 9:00 AM, Johan Jensen <jj@johanjensen.dk> wrote:

I’m not very fond of having just a single dot in front of the method call, as it could easily be missed.
In the case of s.predicate = .hasPrefix("abc"), I would prefer something slightly more expressive.

As it is right now in Swift, accessing methods directly gives you a curried function back, which expects the object instance as argument in the first call, and the rest in the second call.
E.g. String.hasPrefix("abcd")("a") is the same as "abcd".hasPrefix("a")

Flipping the arguments like this:
func flip<A, B, C>(f: A -> B -> C) -> (B -> A -> C) {
    return { valB in
        return { valA in
            return f(valA)(valB)
        }
    }
}

String.hasPrefix("abcd")("a")
let myHasPrefix = flip(String.hasPrefix)
myHasPrefix("a")("abcd")

…would allow us to write the following:
s.predicate = flip(String.hasPrefix("abcd"))

Perhaps it could be extended to something akin to
s.predicate = String::hasPrefix("abcd")

The currying only works for methods and not for properties, so this isn’t currently possible to express like the above:
["John", "Rachel", "Thomas"].map({ $0.endIndex })
["John", "Rachel", "Thomas"].map({ $0.characters.count })

—Johan

On Fri, Dec 18, 2015 at 2:05 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm <mailto:al_skipp@fastmail.fm>> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }

Thanks Al. I should have also pointed out that the syntactic advantage is a bit greater in other contexts where the braces would not replace parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that can improve clarity and readability.

Matthew

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


(Sean Heber) #18

For me there are two sources to the feeling of noise with simple single-statement closures and using $0, etc. - The first are the braces that seem redundant when there’s only a single statement, and the second is the presence of $0.

I played around a bit, and this is probably just a personal preference thing, but I don’t think it’s the $ that bothers me, really, but instead it is the digit that makes it feel noisy. When I change $0 to $a, $b, etc. suddenly the code doesn’t feel so noisy to me. This may simply be because I rarely ever put a number in my variable names, and if I do, I almost always start at 1 and not 0. :stuck_out_tongue: Again, this might just be me. :slight_smile:

    someArray.map({ $0.property })
    someArray.map({ $a.property })

Then it occurred to me that for the simple case of doing a map or filter or whatever using a single method call, what if Swift could instead make an assumption that if there’s a $ variable outside of a closure, we meant to start a single-statement closure so something like this could be possible:

    someArray.map($0.property)
    someArray.map($a.property)

And going farther with this, in the case where there’s only a single argument in the closure, maybe we could skip the number/letter entirely and just use are bare $ instead of $0:

    someArray.map({ $.property })

And finally, combined with the single-statement shortcut:

    someArray.map($.property)

l8r
Sean

···

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

Johan, you are right that all of this is possible but it seems rather verbose to me. I’d rather use the currently possible { $0.member } syntax. The point of the idea is to remove syntactic noise.

It’s reasonable to argue that this isn’t necessary, but in that case the current state suffices IMO. We don’t need a more verbose alternative to what we already have.

On Dec 18, 2015, at 9:00 AM, Johan Jensen <jj@johanjensen.dk> wrote:

I’m not very fond of having just a single dot in front of the method call, as it could easily be missed.
In the case of s.predicate = .hasPrefix("abc"), I would prefer something slightly more expressive.

As it is right now in Swift, accessing methods directly gives you a curried function back, which expects the object instance as argument in the first call, and the rest in the second call.
E.g. String.hasPrefix("abcd")("a") is the same as "abcd".hasPrefix("a")

Flipping the arguments like this:
func flip<A, B, C>(f: A -> B -> C) -> (B -> A -> C) {
    return { valB in
        return { valA in
            return f(valA)(valB)
        }
    }
}

String.hasPrefix("abcd")("a")
let myHasPrefix = flip(String.hasPrefix)
myHasPrefix("a")("abcd")

…would allow us to write the following:
s.predicate = flip(String.hasPrefix("abcd"))

Perhaps it could be extended to something akin to
s.predicate = String::hasPrefix("abcd")

The currying only works for methods and not for properties, so this isn’t currently possible to express like the above:
["John", "Rachel", "Thomas"].map({ $0.endIndex })
["John", "Rachel", "Thomas"].map({ $0.characters.count })

—Johan

On Fri, Dec 18, 2015 at 2:05 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }

Thanks Al. I should have also pointed out that the syntactic advantage is a bit greater in other contexts where the braces would not replace parentheses:

struct S {
  var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that can improve clarity and readability.

Matthew

_______________________________________________
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


(Matthew Johnson) #19

That's an interesting idea. It's a further shorthand for closures rather than an extension of dot shorthand in a new type context. I wonder if this would apply in contexts where the dot shorthand wouldn't.

From a readability point of view I definitely prefer the dot shorthand. The $ after the opening parenthesis doesn't leave enough "whitespace" for my eyes and makes things appear cluttered.

someArray.map($.property)

someArray.map(.property)

That said, I do like the idea of being able to drop the 0 in more complex single-argument closures.

Matthew

···

Sent from my iPad

On Dec 18, 2015, at 10:15 AM, Sean Heber <sean@fifthace.com> wrote:

For me there are two sources to the feeling of noise with simple single-statement closures and using $0, etc. - The first are the braces that seem redundant when there’s only a single statement, and the second is the presence of $0.

I played around a bit, and this is probably just a personal preference thing, but I don’t think it’s the $ that bothers me, really, but instead it is the digit that makes it feel noisy. When I change $0 to $a, $b, etc. suddenly the code doesn’t feel so noisy to me. This may simply be because I rarely ever put a number in my variable names, and if I do, I almost always start at 1 and not 0. :stuck_out_tongue: Again, this might just be me. :slight_smile:

   someArray.map({ $0.property })
   someArray.map({ $a.property })

Then it occurred to me that for the simple case of doing a map or filter or whatever using a single method call, what if Swift could instead make an assumption that if there’s a $ variable outside of a closure, we meant to start a single-statement closure so something like this could be possible:

   someArray.map($0.property)
   someArray.map($a.property)

And going farther with this, in the case where there’s only a single argument in the closure, maybe we could skip the number/letter entirely and just use are bare $ instead of $0:

   someArray.map({ $.property })

And finally, combined with the single-statement shortcut:

   someArray.map($.property)

l8r
Sean

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

Johan, you are right that all of this is possible but it seems rather verbose to me. I’d rather use the currently possible { $0.member } syntax. The point of the idea is to remove syntactic noise.

It’s reasonable to argue that this isn’t necessary, but in that case the current state suffices IMO. We don’t need a more verbose alternative to what we already have.

On Dec 18, 2015, at 9:00 AM, Johan Jensen <jj@johanjensen.dk> wrote:

I’m not very fond of having just a single dot in front of the method call, as it could easily be missed.
In the case of s.predicate = .hasPrefix("abc"), I would prefer something slightly more expressive.

As it is right now in Swift, accessing methods directly gives you a curried function back, which expects the object instance as argument in the first call, and the rest in the second call.
E.g. String.hasPrefix("abcd")("a") is the same as "abcd".hasPrefix("a")

Flipping the arguments like this:
func flip<A, B, C>(f: A -> B -> C) -> (B -> A -> C) {
   return { valB in
       return { valA in
           return f(valA)(valB)
       }
   }
}

String.hasPrefix("abcd")("a")
let myHasPrefix = flip(String.hasPrefix)
myHasPrefix("a")("abcd")

…would allow us to write the following:
s.predicate = flip(String.hasPrefix("abcd"))

Perhaps it could be extended to something akin to
s.predicate = String::hasPrefix("abcd")

The currying only works for methods and not for properties, so this isn’t currently possible to express like the above:
["John", "Rachel", "Thomas"].map({ $0.endIndex })
["John", "Rachel", "Thomas"].map({ $0.characters.count })

—Johan

On Fri, Dec 18, 2015 at 2:05 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 6:52 AM, Al Skipp <al_skipp@fastmail.fm> wrote:

On 18 Dec 2015, at 03:27, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Swift currently offers dot shorthand for static members of type Self in type contexts expecting a value of the type in question. This is most commonly used with enum cases.

Swift does not currently offer shorthand for instance members. Introducing a shorthand for instance members would improve clarity and readability of code in common cases:

anArray.map{$0.anInstanceMethod()}

becomes:

anArray.map(.anInstanceMethod())

This shorthand would work in typing contexts expecting a single argument function. It would allow abbreviated access to any visible instance property getter or instance method on the type of the argument. Of course the return type would need to match the return type expected by the context or a type mismatch compiler error would occur.

The readability advantage is arguably small but it does exist. The feature also aligns very well with an existing language feature.

I think it’s an interesting idea and am wondering whether others feel like it is something worth pursuing or not.

Matthew

I’d be interested to hear peoples thoughts regarding this proposal. I’m personally in favour, but perhaps there are potential issues with the suggestion?

It’s only a small visual change, but I think it is a syntactic improvement. Let’s pretend for a moment that the current syntax was:
anArray.map(.anInstanceMethod())

I’m not sure many people would argue for it to be changed to:
anArray.map { $0.anInstanceMethod() }

Thanks Al. I should have also pointed out that the syntactic advantage is a bit greater in other contexts where the braces would not replace parentheses:

struct S {
var predicate: String -> Bool
}

var s = S()
s.predicate = { $0.hasPrefix(“abc”) }

vs
s.predicate = .hasPrefix(“abc”)

It’s not a super important change, but maybe a low-hanging fruit item that can improve clarity and readability.

Matthew

_______________________________________________
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


(Tino) #20

As it is right now in Swift, accessing methods directly gives you a curried function back, which expects the object instance as argument in the first call, and the rest in the second call.

That was my first thought when I read the proposal - and as there is already a change planned for currying, it could be easy to change the way it works for methods.

I really don't think that ".method()" improves clarity, but "Type.method" definitely does.