Pitch: Compound name `foo(:)` for nullary functions

Oh, good point! Hrmm… “foo(#null)”/“foo(#nullary)"? I can’t imagine either of those would ever be valid function calls, and they get the point across (the later more than the former, but it’s more to type). I don’t like that syntax for the name of “shortest” version of the function isn’t shorter than the syntax of the name for other versions of the function, though.

- Dave Sweeris

···

On Feb 22, 2017, at 11:05 AM, Matthew Johnson <matthew@anandabits.com> wrote:

On Feb 22, 2017, at 12:30 PM, David Sweeris <davesweeris@mac.com> wrote:

On Feb 22, 2017, at 7:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

I like this idea. I think you made the right choice of syntax given the alternatives considered. To me `foo(_)` and `foo(:)` equally imply presence of an argument. The former looks like an anonymous (unnamed) argument and the latter includes the colon which only follows an argument. Between the two `foo(:)` is the better choice because it doesn’t look like a pattern as has been pointed out.

I’m going to do a little brainstorming to try and come up with something that works and doesn’t imply an argument at all but suspect I’ll come up empty handed.

What about “foo(Void)”? It might be fairly easily confused with “foo(:Void)”, but in practice, how likely is it for someone to declare both `foo()` and `foo(_: Void)`?

I almost threw out `foo(Void)` and `foo(Never)` as ideas. There is at least one problem with these. We will hopefully eventually get rid of the need to say `.self` in expressions like `Int.self`. If we are able to do that then `foo(Void)` and `foo(Never)` are syntactically valid function calls.

There were some opinions on Slack that we should simply change `foo` so
that it can *only* refer to the nullary version.

That'd be a source-breaking change, but I'm also not sure whether it's even
solve the problem — is it true you might still have both a function and a
variable named foo accessible in the same scope?

···

On Wed, Feb 22, 2017 at 11:48 AM David Sweeris <davesweeris@mac.com> wrote:

> On Feb 22, 2017, at 11:05 AM, Matthew Johnson <matthew@anandabits.com> > wrote:
>
>
>> On Feb 22, 2017, at 12:30 PM, David Sweeris <davesweeris@mac.com> > wrote:
>>
>>
>>> On Feb 22, 2017, at 7:48 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:
>>>
>>> I like this idea. I think you made the right choice of syntax given
the alternatives considered. To me `foo(_)` and `foo(:)` equally imply
presence of an argument. The former looks like an anonymous (unnamed)
argument and the latter includes the colon which only follows an argument.
Between the two `foo(:)` is the better choice because it doesn’t look like
a pattern as has been pointed out.
>>>
>>> I’m going to do a little brainstorming to try and come up with
something that works and doesn’t imply an argument at all but suspect I’ll
come up empty handed.
>>
>> What about “foo(Void)”? It might be fairly easily confused with
“foo(:Void)”, but in practice, how likely is it for someone to declare both
`foo()` and `foo(_: Void)`?
>
> I almost threw out `foo(Void)` and `foo(Never)` as ideas. There is at
least one problem with these. We will hopefully eventually get rid of the
need to say `.self` in expressions like `Int.self`. If we are able to do
that then `foo(Void)` and `foo(Never)` are syntactically valid function
calls.

Oh, good point! Hrmm… “foo(#null)”/“foo(#nullary)"? I can’t imagine either
of those would ever be valid function calls, and they get the point across
(the later more than the former, but it’s more to type). I don’t like that
syntax for the name of “shortest” version of the function isn’t shorter
than the syntax of the name for other versions of the function, though.

- Dave Sweeris

Just to throw out some other options: foo(#) and foo(@).

(And you thought we'd gotten rid of # argument labels! :wink:)

···

On Wed, Feb 22, 2017 at 11:48 AM David Sweeris <davesweeris@mac.com> wrote:

> On Feb 22, 2017, at 11:05 AM, Matthew Johnson <matthew@anandabits.com> > wrote:
>
>
>> On Feb 22, 2017, at 12:30 PM, David Sweeris <davesweeris@mac.com> > wrote:
>>
>>
>>> On Feb 22, 2017, at 7:48 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:
>>>
>>> I like this idea. I think you made the right choice of syntax given
the alternatives considered. To me `foo(_)` and `foo(:)` equally imply
presence of an argument. The former looks like an anonymous (unnamed)
argument and the latter includes the colon which only follows an argument.
Between the two `foo(:)` is the better choice because it doesn’t look like
a pattern as has been pointed out.
>>>
>>> I’m going to do a little brainstorming to try and come up with
something that works and doesn’t imply an argument at all but suspect I’ll
come up empty handed.
>>
>> What about “foo(Void)”? It might be fairly easily confused with
“foo(:Void)”, but in practice, how likely is it for someone to declare both
`foo()` and `foo(_: Void)`?
>
> I almost threw out `foo(Void)` and `foo(Never)` as ideas. There is at
least one problem with these. We will hopefully eventually get rid of the
need to say `.self` in expressions like `Int.self`. If we are able to do
that then `foo(Void)` and `foo(Never)` are syntactically valid function
calls.

Oh, good point! Hrmm… “foo(#null)”/“foo(#nullary)"? I can’t imagine either
of those would ever be valid function calls, and they get the point across
(the later more than the former, but it’s more to type). I don’t like that
syntax for the name of “shortest” version of the function isn’t shorter
than the syntax of the name for other versions of the function, though.

- Dave Sweeris

This is clean, but given knowledge of foo(bar:) syntax, its discoverability
is low. Conversely, given knowledge of `foo()`, the discoverability of
foo(bar:) would be low compared to `foo(bar:)`.

If backticks were the *only* option, and also worked as `foo(bar:)`, the
consistency would be appealing. Although then if you had a function name
which needed backticks, `foo`(bar:) would have to continue working, I
suppose, so only allowing `foo(bar:)` isn't feasible.

I imagine this would make for some very nice code completion, though —
`foo(#^...^# could suggest the names of all the foo variants.

···

On Thu, Feb 23, 2017 at 6:36 AM, Ben Rimmington <me@benrimmington.com> wrote:

> On 23 Feb 2017, at 14:23, Xiaodi Wu wrote:
>
> What happens when you need the backticks for the function name itself?
We can't nest them.

func `class`() {}

`class`() // Function call.

`class()` // Function reference.

-- Ben

Nice. That works well.

···

On Thu, Feb 23, 2017 at 08:36 Ben Rimmington <me@benrimmington.com> wrote:

> On 23 Feb 2017, at 14:23, Xiaodi Wu wrote:
>
> What happens when you need the backticks for the function name itself?
We can't nest them.

func `class`() {}

`class`() // Function call.

`class()` // Function reference.

-- Ben

FWIW, I do think the foo(_) is the best variant. For me it means "no argument label AND no argument at all, as there is no `:` in it".
foo(_:) means "no argument label BUT one argument". etc.
As for `class()` IMO it is too cryptic. class(_) is more clear about what it *is*(because of _ as parameters, that symbol is not used when we call the func but used when we define a reference to it, like class(_:), class(_:something:)

···

On 23.02.2017 17:36, Ben Rimmington via swift-evolution wrote:

On 23 Feb 2017, at 14:23, Xiaodi Wu wrote:

What happens when you need the backticks for the function name itself? We can't nest them.

func `class`() {}

`class`() // Function call.

`class()` // Function reference.

-- Ben

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

Given that \foo(bar:baz:) will work, and that \foo() will be unambiguously
distinguished from foo(), I think that would be the only logical result.

···

On Thu, Apr 6, 2017 at 00:40 Jacob Bandes-Storch via swift-evolution < swift-evolution@swift.org> wrote:

Now that escaping with \ has been proposed for KeyPaths, this makes me
wonder whether it would be appropriate to use "\foo()" rather than
"foo(_)"/"foo(:)" ? It still feels a bit strange, as \foo() looks like
escaping the *result* of a call.

On Sat, Feb 25, 2017 at 1:43 PM, David Hart <david@hartbit.com> wrote:

On 25 Feb 2017, at 00:56, Jordan Rose via swift-evolution < > swift-evolution@swift.org> wrote:

I don't have a *good* answer for this, but I'll vote *against* 'foo(:)'
because that's what a lot of people think the name of 'foo(_:)' should be.
I'd rather be able to offer fix-its for that even when you have both
'foo()' and 'foo(_:)' defined. I'd rather go with 'foo(_)' despite the tiny
ambiguity in pattern contexts.

(I'm personally in favor of killing unapplied function references
altogether in favor of closures, on the grounds that they are overly terse,
make type-checking more complicated, and often lead to retain cycles. Then
we'd only need this for selector, and it's perfectly unambiguous to use
'foo()' there. But I wasn't planning to fight that particular battle now,
and it is rather annoying to require the 'as' in the meantime.)

It is potentially going to be hard to fight that battle. I think a lot of
functional/Haskell people love them and would be sad to see them go away (I
plead guilty). But it isn’t a well known part of the language so I don’t
think the general community would miss it.

Jordan

On Feb 21, 2017, at 23:05, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Evolutioniers,

*Compound name syntax* — foo(_:), foo(bar:), foo(bar:baz:) — is used to
disambiguate references to functions. (You might've used it inside a
selector expression.) But there's currently no compound name for a
function with no arguments.

    func foo() {} // no compound syntax for this one :(
    func foo(_ bar: Int) {} // foo(_:)
    func foo(bar: Int) {} // foo(bar:)
    func foo(bar: String, baz: Double) {} // foo(bar:baz:)

Given these four functions, only the first one has no compound name
syntax. And the simple reference "let myfn = foo" is ambiguous because it
could refer to any of the four. A workaround is to specify a contextual
type, e.g. "let myfn = foo as () -> Void".

I filed SR-3550 <Issues · apple/swift-issues · GitHub; for this a while
ago, and there was some discussion in JIRA about it. I'd like to continue
exploring solutions here and then write up a formal proposal.

To kick off the discussion, *I'd like to propose foo(:) for nullary
functions.*

Advantages:
- the colon marks a clear similarity to the foo(bar:) form when argument
labels are present.
- cutely parallels the empty dictionary literal, [:].

Disadvantages:
- violates intuition about one-colon-per-argument.
- the parallel between selector(foo(:)) and @selector(foo) is not quite
as obvious as between selector(foo(_:)) and @selector(foo:).

For the sake of discussion, another option would be *foo(_)*. This was my
original choice, and I like that the number of colons matches the number of
parameters. However, it's a little less obvious as a function reference. It
would preclude _ from acting as an actual identifier, and might conflict
with pattern-matching syntax (although it appears functions can't be
compared with ~= anyway).

Looking forward to everyone's bikeshed color ideas,
Jacob

_______________________________________________
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

Between the two, I’d prefer “foo(#)”, but I don’t think either are very intuitive.

- Dave Sweeris

···

On Feb 22, 2017, at 12:27 PM, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Just to throw out some other options: foo(#) and foo(@).

(And you thought we'd gotten rid of # argument labels! :wink:)

Although come to think of it, neither are either of my suggestions.

- Dave Sweeris

···

On Feb 22, 2017, at 1:59 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 22, 2017, at 12:27 PM, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Just to throw out some other options: foo(#) and foo(@).

(And you thought we'd gotten rid of # argument labels! :wink:)

Between the two, I’d prefer “foo(#)”, but I don’t think either are very intuitive.

Agreed, but it seems like every suggestion other than “foo(:)” which doesn’t use such a character ends up potentially conflicting with some other aspect of functions. That example Rintaro Ishizaki posted about the potential confusion regarding “_” in switch statements doesn’t compile now, but I’m not sure if there isn’t some useful advanced pattern-matching stuff that might need that syntax. And we don’t like “foo(:)” because it breaks the “colon -> argument” rule that exists in the rest of the language.

- Dave Sweeris

···

On Feb 22, 2017, at 2:12 PM, Richard Wei <rxrwei@gmail.com> wrote:

In addition, I think # and @ are very confusing since they are not one of the existing symbols in function name syntax.

I prefer the `foo(_)` option and keeping the one-colon-per-arg rule.

Intuition:
Underscore means no label. Colon means one argument.
foo(_:) – one arg with no label
foo(_) – no arg with no label

-Richard

···

On Feb 22, 2017, at 14:27, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Just to throw out some other options: foo(#) and foo(@).

(And you thought we'd gotten rid of # argument labels! :wink:)

On Wed, Feb 22, 2017 at 11:48 AM David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

> On Feb 22, 2017, at 11:05 AM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
>
>
>> On Feb 22, 2017, at 12:30 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:
>>
>>
>>> On Feb 22, 2017, at 7:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>
>>> I like this idea. I think you made the right choice of syntax given the alternatives considered. To me `foo(_)` and `foo(:)` equally imply presence of an argument. The former looks like an anonymous (unnamed) argument and the latter includes the colon which only follows an argument. Between the two `foo(:)` is the better choice because it doesn’t look like a pattern as has been pointed out.
>>>
>>> I’m going to do a little brainstorming to try and come up with something that works and doesn’t imply an argument at all but suspect I’ll come up empty handed.
>>
>> What about “foo(Void)”? It might be fairly easily confused with “foo(:Void)”, but in practice, how likely is it for someone to declare both `foo()` and `foo(_: Void)`?
>
> I almost threw out `foo(Void)` and `foo(Never)` as ideas. There is at least one problem with these. We will hopefully eventually get rid of the need to say `.self` in expressions like `Int.self`. If we are able to do that then `foo(Void)` and `foo(Never)` are syntactically valid function calls.

Oh, good point! Hrmm… “foo(#null)”/“foo(#nullary)"? I can’t imagine either of those would ever be valid function calls, and they get the point across (the later more than the former, but it’s more to type). I don’t like that syntax for the name of “shortest” version of the function isn’t shorter than the syntax of the name for other versions of the function, though.

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

In addition, I think # and @ are very confusing since they are not one of the existing symbols in function name syntax.

-Richard

···

On Feb 22, 2017, at 15:25, Richard Wei <rxrwei@gmail.com> wrote:

I prefer the `foo(_)` option and keeping the one-colon-per-arg rule.

Intuition:
Underscore means no label. Colon means one argument.
foo(_:) – one arg with no label
foo(_) – no arg with no label

-Richard

On Feb 22, 2017, at 14:27, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Just to throw out some other options: foo(#) and foo(@).

(And you thought we'd gotten rid of # argument labels! :wink:)

On Wed, Feb 22, 2017 at 11:48 AM David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

> On Feb 22, 2017, at 11:05 AM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
>
>
>> On Feb 22, 2017, at 12:30 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:
>>
>>
>>> On Feb 22, 2017, at 7:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>
>>> I like this idea. I think you made the right choice of syntax given the alternatives considered. To me `foo(_)` and `foo(:)` equally imply presence of an argument. The former looks like an anonymous (unnamed) argument and the latter includes the colon which only follows an argument. Between the two `foo(:)` is the better choice because it doesn’t look like a pattern as has been pointed out.
>>>
>>> I’m going to do a little brainstorming to try and come up with something that works and doesn’t imply an argument at all but suspect I’ll come up empty handed.
>>
>> What about “foo(Void)”? It might be fairly easily confused with “foo(:Void)”, but in practice, how likely is it for someone to declare both `foo()` and `foo(_: Void)`?
>
> I almost threw out `foo(Void)` and `foo(Never)` as ideas. There is at least one problem with these. We will hopefully eventually get rid of the need to say `.self` in expressions like `Int.self`. If we are able to do that then `foo(Void)` and `foo(Never)` are syntactically valid function calls.

Oh, good point! Hrmm… “foo(#null)”/“foo(#nullary)"? I can’t imagine either of those would ever be valid function calls, and they get the point across (the later more than the former, but it’s more to type). I don’t like that syntax for the name of “shortest” version of the function isn’t shorter than the syntax of the name for other versions of the function, though.

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

Yep, I think the backtick option is the best so far.

- Dave Sweeris

···

On Feb 23, 2017, at 06:49, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Nice. That works well.

On Thu, Feb 23, 2017 at 08:36 Ben Rimmington <me@benrimmington.com> wrote:

> On 23 Feb 2017, at 14:23, Xiaodi Wu wrote:
>
> What happens when you need the backticks for the function name itself? We can't nest them.

func `class`() {}

`class`() // Function call.

`class()` // Function reference.

Does swift still use #?

foo(#)

It might be more obvious then

foo(_)

People might mistake it for foo(_:) if they are just glancing at it.

But foo(#) looks special.

···

On Thu, Feb 23, 2017 at 1:07 PM Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

FWIW, I do think the foo(_) is the best variant. For me it means "no
argument label AND no argument at all, as there is no `:` in it".
foo(_:) means "no argument label BUT one argument". etc.
As for `class()` IMO it is too cryptic. class(_) is more clear about what
it *is*(because of _ as parameters, that symbol is not used when we call
the func but used when we define a reference to it, like class(_:),
class(_:something:)

On 23.02.2017 17:36, Ben Rimmington via swift-evolution wrote:
>
>> On 23 Feb 2017, at 14:23, Xiaodi Wu wrote:
>>
>> What happens when you need the backticks for the function name itself?
We can't nest them.
>
> func `class`() {}
>
> `class`() // Function call.
>
> `class()` // Function reference.
>
> -- Ben
>
> _______________________________________________
> 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

Given that \foo(bar:baz:) will work, and that \foo() will be unambiguously distinguished from foo(), I think that would be the only logical result.

Agree. It seem like this would fit nicely into the revision of SE-0042 that Doug mentioned.

···

On Apr 6, 2017, at 7:02 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 6, 2017 at 00:40 Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Now that escaping with \ has been proposed for KeyPaths, this makes me wonder whether it would be appropriate to use "\foo()" rather than "foo(_)"/"foo(:)" ? It still feels a bit strange, as \foo() looks like escaping the result of a call.

On Sat, Feb 25, 2017 at 1:43 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 25 Feb 2017, at 00:56, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I don't have a good answer for this, but I'll vote against 'foo(:)' because that's what a lot of people think the name of 'foo(_:)' should be. I'd rather be able to offer fix-its for that even when you have both 'foo()' and 'foo(_:)' defined. I'd rather go with 'foo(_)' despite the tiny ambiguity in pattern contexts.

(I'm personally in favor of killing unapplied function references altogether in favor of closures, on the grounds that they are overly terse, make type-checking more complicated, and often lead to retain cycles. Then we'd only need this for selector, and it's perfectly unambiguous to use 'foo()' there. But I wasn't planning to fight that particular battle now, and it is rather annoying to require the 'as' in the meantime.)

It is potentially going to be hard to fight that battle. I think a lot of functional/Haskell people love them and would be sad to see them go away (I plead guilty). But it isn’t a well known part of the language so I don’t think the general community would miss it.

Jordan

On Feb 21, 2017, at 23:05, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

Evolutioniers,

Compound name syntax — foo(_:), foo(bar:), foo(bar:baz:) — is used to disambiguate references to functions. (You might've used it inside a selector expression.) But there's currently no compound name for a function with no arguments.

    func foo() {} // no compound syntax for this one :(
    func foo(_ bar: Int) {} // foo(_:)
    func foo(bar: Int) {} // foo(bar:)
    func foo(bar: String, baz: Double) {} // foo(bar:baz:)

Given these four functions, only the first one has no compound name syntax. And the simple reference "let myfn = foo" is ambiguous because it could refer to any of the four. A workaround is to specify a contextual type, e.g. "let myfn = foo as () -> Void".

I filed SR-3550 <Issues · apple/swift-issues · GitHub; for this a while ago, and there was some discussion in JIRA about it. I'd like to continue exploring solutions here and then write up a formal proposal.

To kick off the discussion, I'd like to propose foo(:) for nullary functions.

Advantages:
- the colon marks a clear similarity to the foo(bar:) form when argument labels are present.
- cutely parallels the empty dictionary literal, [:].

Disadvantages:
- violates intuition about one-colon-per-argument.
- the parallel between selector(foo(:)) and @selector(foo) is not quite as obvious as between selector(foo(_:)) and @selector(foo:).

For the sake of discussion, another option would be foo(_). This was my original choice, and I like that the number of colons matches the number of parameters. However, it's a little less obvious as a function reference. It would preclude _ from acting as an actual identifier, and might conflict with pattern-matching syntax (although it appears functions can't be compared with ~= anyway).

Looking forward to everyone's bikeshed color ideas,
Jacob

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

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

Agree.

···

On Apr 6, 2017, at 8:02 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Given that \foo(bar:baz:) will work, and that \foo() will be unambiguously distinguished from foo(), I think that would be the only logical result.

On Thu, Apr 6, 2017 at 00:40 Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Now that escaping with \ has been proposed for KeyPaths, this makes me wonder whether it would be appropriate to use "\foo()" rather than "foo(_)"/"foo(:)" ? It still feels a bit strange, as \foo() looks like escaping the result of a call.

On Sat, Feb 25, 2017 at 1:43 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 25 Feb 2017, at 00:56, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I don't have a good answer for this, but I'll vote against 'foo(:)' because that's what a lot of people think the name of 'foo(_:)' should be. I'd rather be able to offer fix-its for that even when you have both 'foo()' and 'foo(_:)' defined. I'd rather go with 'foo(_)' despite the tiny ambiguity in pattern contexts.

(I'm personally in favor of killing unapplied function references altogether in favor of closures, on the grounds that they are overly terse, make type-checking more complicated, and often lead to retain cycles. Then we'd only need this for selector, and it's perfectly unambiguous to use 'foo()' there. But I wasn't planning to fight that particular battle now, and it is rather annoying to require the 'as' in the meantime.)

It is potentially going to be hard to fight that battle. I think a lot of functional/Haskell people love them and would be sad to see them go away (I plead guilty). But it isn’t a well known part of the language so I don’t think the general community would miss it.

Jordan

On Feb 21, 2017, at 23:05, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

Evolutioniers,

Compound name syntax — foo(_:), foo(bar:), foo(bar:baz:) — is used to disambiguate references to functions. (You might've used it inside a selector expression.) But there's currently no compound name for a function with no arguments.

    func foo() {} // no compound syntax for this one :(
    func foo(_ bar: Int) {} // foo(_:)
    func foo(bar: Int) {} // foo(bar:)
    func foo(bar: String, baz: Double) {} // foo(bar:baz:)

Given these four functions, only the first one has no compound name syntax. And the simple reference "let myfn = foo" is ambiguous because it could refer to any of the four. A workaround is to specify a contextual type, e.g. "let myfn = foo as () -> Void".

I filed SR-3550 <Issues · apple/swift-issues · GitHub; for this a while ago, and there was some discussion in JIRA about it. I'd like to continue exploring solutions here and then write up a formal proposal.

To kick off the discussion, I'd like to propose foo(:) for nullary functions.

Advantages:
- the colon marks a clear similarity to the foo(bar:) form when argument labels are present.
- cutely parallels the empty dictionary literal, [:].

Disadvantages:
- violates intuition about one-colon-per-argument.
- the parallel between selector(foo(:)) and @selector(foo) is not quite as obvious as between selector(foo(_:)) and @selector(foo:).

For the sake of discussion, another option would be foo(_). This was my original choice, and I like that the number of colons matches the number of parameters. However, it's a little less obvious as a function reference. It would preclude _ from acting as an actual identifier, and might conflict with pattern-matching syntax (although it appears functions can't be compared with ~= anyway).

Looking forward to everyone's bikeshed color ideas,
Jacob

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

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

Incidentally--and I suppose I will have to repeat myself somewhere else in
the likely case that this is not seen by the people who are designing this
feature--using the sigil syntax `\foo()` nicely solves the nullary function
problem, but we get another ambiguity with the introduction of key paths
and function references using the same syntax:

Currently, it is possible to have a member `var foo` and another `func
foo(bar:baz:)` in the same type. There is no real necessity to forbid that,
though I doubt it would break too many people's code. (I did, however, once
suggest naming `FloatingPoint.ulpOfOne` to simply `FloatingPoint.ulp`,
which would have taken advantage of this rule.)

In such a scenario, `\foo` becomes ambiguous. It would be sufficient to say
that in such scenarios `\foo` is always interpreted as referring to `var
foo`, while `\foo(bar:baz:)` becomes the only way of writing a reference to
the function.

···

On Thu, Apr 6, 2017 at 9:59 AM, Ricardo Parada <rparada@mac.com> wrote:

Agree.

On Apr 6, 2017, at 8:02 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

Given that \foo(bar:baz:) will work, and that \foo() will be unambiguously
distinguished from foo(), I think that would be the only logical result.

On Thu, Apr 6, 2017 at 00:40 Jacob Bandes-Storch via swift-evolution < > swift-evolution@swift.org> wrote:

Now that escaping with \ has been proposed for KeyPaths, this makes me
wonder whether it would be appropriate to use "\foo()" rather than
"foo(_)"/"foo(:)" ? It still feels a bit strange, as \foo() looks like
escaping the *result* of a call.

On Sat, Feb 25, 2017 at 1:43 PM, David Hart <david@hartbit.com> wrote:

On 25 Feb 2017, at 00:56, Jordan Rose via swift-evolution < >> swift-evolution@swift.org> wrote:

I don't have a *good* answer for this, but I'll vote *against* 'foo(:)'
because that's what a lot of people think the name of 'foo(_:)' should be.
I'd rather be able to offer fix-its for that even when you have both
'foo()' and 'foo(_:)' defined. I'd rather go with 'foo(_)' despite the tiny
ambiguity in pattern contexts.

(I'm personally in favor of killing unapplied function references
altogether in favor of closures, on the grounds that they are overly terse,
make type-checking more complicated, and often lead to retain cycles. Then
we'd only need this for selector, and it's perfectly unambiguous to use
'foo()' there. But I wasn't planning to fight that particular battle now,
and it is rather annoying to require the 'as' in the meantime.)

It is potentially going to be hard to fight that battle. I think a lot of
functional/Haskell people love them and would be sad to see them go away (I
plead guilty). But it isn’t a well known part of the language so I don’t
think the general community would miss it.

Jordan

On Feb 21, 2017, at 23:05, Jacob Bandes-Storch <jtbandes@gmail.com> >> wrote:

Evolutioniers,

*Compound name syntax* — foo(_:), foo(bar:), foo(bar:baz:) — is used to
disambiguate references to functions. (You might've used it inside a
selector expression.) But there's currently no compound name for a
function with no arguments.

    func foo() {} // no compound syntax for this one :(
    func foo(_ bar: Int) {} // foo(_:)
    func foo(bar: Int) {} // foo(bar:)
    func foo(bar: String, baz: Double) {} // foo(bar:baz:)

Given these four functions, only the first one has no compound name
syntax. And the simple reference "let myfn = foo" is ambiguous because
it could refer to any of the four. A workaround is to specify a contextual
type, e.g. "let myfn = foo as () -> Void".

I filed SR-3550 <Issues · apple/swift-issues · GitHub; for this a while
ago, and there was some discussion in JIRA about it. I'd like to continue
exploring solutions here and then write up a formal proposal.

To kick off the discussion, *I'd like to propose foo(:) for nullary
functions.*

Advantages:
- the colon marks a clear similarity to the foo(bar:) form when argument
labels are present.
- cutely parallels the empty dictionary literal, [:].

Disadvantages:
- violates intuition about one-colon-per-argument.
- the parallel between selector(foo(:)) and @selector(foo) is not quite
as obvious as between selector(foo(_:)) and @selector(foo:).

For the sake of discussion, another option would be *foo(_)*. This was
my original choice, and I like that the number of colons matches the number
of parameters. However, it's a little less obvious as a function reference.
It would preclude _ from acting as an actual identifier, and might conflict
with pattern-matching syntax (although it appears functions can't be
compared with ~= anyway).

Looking forward to everyone's bikeshed color ideas,
Jacob

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

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

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

There were some opinions on Slack that we should simply change `foo` so that it can *only* refer to the nullary version.

I think this is the right solution. Eventually we want to get to the point where parameter labels are part of a compound name; at that point, it'd be natural for a zero-argument function to just have its name be the base name.

That'd be a source-breaking change,

We can always support looking up members by base name only as an unprincipled shorthand. (But to tell the truth, I'd prefer to just break them.)

but I'm also not sure whether it's even solve the problem — is it true you might still have both a function and a variable named foo accessible in the same scope?

The simple version is illegal:

  Welcome to Apple Swift version 3.1 (swiftlang-802.0.41 clang-802.0.36). Type :help for assistance.
    1> struct X { var x: Int; func x() {} }
  error: repl.swift:1:29: error: invalid redeclaration of 'x()'
  struct X { var x: Int; func x() {} }
                              ^
  
  repl.swift:1:16: note: 'x' previously declared here
  struct X { var x: Int; func x() {} }
                 ^

I have a sneaking suspicion there actually *are* circumstances where it's possible—but I think there probably shouldn't be.

Of the main options discussed—`foo(_)` vs `foo(:)`—I think the underscore is more accurate. It does conflict with pattern matching syntax, but I don't think you can match a (0-ary) function value against anything anyway, so I don't think that matters in practice.

···

On Feb 22, 2017, at 12:24 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

--
Brent Royal-Gordon
Architechies

There were some opinions on Slack that we should simply change `foo` so
that it can *only* refer to the nullary version.

I think this is the right solution. Eventually we want to get to the point
where parameter labels are part of a compound name; at that point, it'd be
natural for a zero-argument function to just have its name be the base name.

With the sigil, this seems like a half-way solution. If we are to remove
base name-only lookups, the zero-argument function can be unambiguously
spelled `\foo()` and we can leave `\foo` to refer only to variables named
"foo" without a compound name.

That'd be a source-breaking change,

We can always support looking up members by base name only as an
unprincipled shorthand. (But to tell the truth, I'd prefer to just break
them.)

but I'm also not sure whether it's even solve the problem — is it true you
might still have both a function and a variable named foo accessible in the
same scope?

The simple version is illegal:

Welcome to Apple Swift version 3.1 (swiftlang-802.0.41 clang-802.0.36).
Type :help for assistance.
  1> struct X { var x: Int; func x() {} }
error: repl.swift:1:29: error: invalid redeclaration of 'x()'
struct X { var x: Int; func x() {} }
                            ^

repl.swift:1:16: note: 'x' previously declared here
struct X { var x: Int; func x() {} }
               ^

No, but this is legal:

struct S {
var foo: Int = 42
func foo(_ bar: Int = 42) {
print("Hello, world!")
}
}

I have a sneaking suspicion there actually *are* circumstances where it's

possible—but I think there probably shouldn't be.

There are legitimate designs that might make use of this (see the `ulp`
example above); whether it's wise or not is a different matter.

···

On Sat, Apr 8, 2017 at 7:15 PM, Brent Royal-Gordon via swift-evolution < swift-evolution@swift.org> wrote:

On Feb 22, 2017, at 12:24 PM, Jacob Bandes-Storch via swift-evolution < > swift-evolution@swift.org> wrote:

Of the main options discussed—`foo(_)` vs `foo(:)`—I think the underscore
is more accurate. It does conflict with pattern matching syntax, but I
don't think you can match a (0-ary) function value against anything anyway,
so I don't think that matters in practice.

--
Brent Royal-Gordon
Architechies

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