[Proposal draft] Generalized Naming for Any Function

I’m bothered by it because it overloads backtick to mean two things: keywords-as-names, and annoying-sequences-of-tokens-as-names. Either use would be acceptable to me, but the fact that we have to support one nested inside the other makes it pretty nasty.

-Chris

···

On Dec 27, 2015, at 4:27 PM, John McCall <rjmccall@apple.com> wrote:

On Dec 27, 2015, at 4:15 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 27, 2015, at 4:09 PM, John McCall <rjmccall@apple.com> wrote:

I’m a fan of good error recovery, but I don’t think it is a major concern here for two reasons:

1) The most common case in a method will lack a label, and "thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried reference.
2) A common case of accidentally completing a nullary call (thing.foo() vs thing.foo) will produce a type error. We already produce good QoI for an unapplied function - adding the inverse would be simple.

Further, it will be uncommon *in general* to form a curried reference, so error recovery doesn’t have to be perfect in all the edge cases. As with other commenters, if it is at all possible to avoid the extra backticks, I’d really prefer that.

The concern, I think, is that a messed-up normal call might look like a curried reference.

My inclination would be to go the other way: if we get a syntax for this that we like, I think we should use it for *all* curried member references, and reject things like foo.bar in favor of foo.`bar`. The ability to write foo.bar for a method has always struck me as more clever than wise, to be honest.

If you were to go that far, I’d suggest looking at this as a different version of the “." operator. If you resyntax curried to something else like (just a strawman, intentionally ugly syntax):

  foo.#bar

Then you’d get a nice property that the plain old dot operator always has to be fully applied. This certainly would be a win for error recovery. Also, if you did this, you wouldn’t need the backticks from doug’s proposal either for things like:

  foo.#bar(param1:param2:)

either.

Right. I really like this effect.

I’m not that bothered by requiring the backticks, especially because it generalizes well to non-member function references, which I’m not sure any sort of different-member-access syntax does.

How to differentiate these functions?

class A{
    func someFunc(a: Int) -> Int{
        return 0;
    }
    func someFunc(a: Int) -> Double{
        return 0;
    }
    func someFunc(a: Double) -> Int{
        return 0;
    }
    func someFunc(a: Double) -> Double{
        return 0;
    }
   func someFunc(a: Int, b: Int) -> Int{
        return 0;
    }
}

Even with backticks would not be possible.

You may need to reference the method signature altogether.

var someA = A()

*let fn1 = someA.#someFunc(a: Int) -> Int*

*let fn2 = someA.#someFunc(a: Int) -> Double let fn3 = someA.#someFunc(a:
Double) -> Int let fn4 = someA.#someFunc(a: Double) -> Double*

An operator at the beginning perhaps?

let fn1 = #someA.someFunc(a: Int) -> Int
let fn2 = #someA.someFunc(a: Int) -> Double
let fn3 = #someA.someFunc(a: Double) -> Int
let fn4 = #someA.someFunc(a: Double) -> Double

You may not need the full signature all the time, only necessary to
differentiate.

extension A {
    func someOtherFunc(a: Int, b: Int) -> Int{
        return 0;
    }
    func someOtherFunc(){
    }
    func someOther(){
    }
}

*let fn5 = someA.#someOtherFunc(a:, b:)*
*let fn6 = someA.#someOtherFunc()*
*let fn6 = someA.someOther*

Another possibility:

*let fn5 = #(someA.someOtherFunc(a:, b:))*
*let fn5 = @(someA.someOtherFunc(a:, b:))*

Thus the parser can try to just focus on what's inside the *#(*...*) or *
*@(*...*)*

···

Em dom, 27 de dez de 2015 às 22:27, John McCall via swift-evolution < swift-evolution@swift.org> escreveu:

> On Dec 27, 2015, at 4:15 PM, Chris Lattner <clattner@apple.com> wrote:
>
> On Dec 27, 2015, at 4:09 PM, John McCall <rjmccall@apple.com> wrote:
>>> I’m a fan of good error recovery, but I don’t think it is a major
concern here for two reasons:
>>>
>>> 1) The most common case in a method will lack a label, and
"thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried
reference.
>>> 2) A common case of accidentally completing a nullary call
(thing.foo() vs thing.foo) will produce a type error. We already produce
good QoI for an unapplied function - adding the inverse would be simple.
>>>
>>> Further, it will be uncommon *in general* to form a curried reference,
so error recovery doesn’t have to be perfect in all the edge cases. As
with other commenters, if it is at all possible to avoid the extra
backticks, I’d really prefer that.
>>
>> The concern, I think, is that a messed-up normal call might look like a
curried reference.
>>
>> My inclination would be to go the other way: if we get a syntax for
this that we like, I think we should use it for *all* curried member
references, and reject things like foo.bar in favor of foo.`bar`. The
ability to write foo.bar for a method has always struck me as more clever
than wise, to be honest.
>
> If you were to go that far, I’d suggest looking at this as a different
version of the “." operator. If you resyntax curried to something else
like (just a strawman, intentionally ugly syntax):
>
> foo.#bar
>
> Then you’d get a nice property that the plain old dot operator always
has to be fully applied. This certainly would be a win for error
recovery. Also, if you did this, you wouldn’t need the backticks from
doug’s proposal either for things like:
>
> foo.#bar(param1:param2:)
>
> either.

Right. I really like this effect.

I’m not that bothered by requiring the backticks, especially because it
generalizes well to non-member function references, which I’m not sure any
sort of different-member-access syntax does.

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

So the contextual lookup rule would be:

If the expression
  .foo
or
  .foo(E…)
is known from context to yield a value of type T, then:
  if T is a nominal type, the expression is equivalent to T.foo(E…);
  if T is a function type (inout? U -> V), then the expression is equivalent to { (x: inout? U) in x.foo(E…) };
  if T is a lens function type (inout? U -> inout V), then the argument expression (E…) shall not be present and the expression shall be equivalent to { (x: inout? U) in &x.foo }, or whatever the “applied” lens syntax is;
otherwise the expression is ill-formed.

This would be an obstacle to allowing extension methods on a hypothetical Swift.Function<X,Y> type, but I think that’s an acceptable sacrifice.

John.

···

On Dec 28, 2015, at 1:14 PM, Joe Groff <jgroff@apple.com> wrote:

On Dec 28, 2015, at 1:09 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

and you could access the unapplied lens for an instance property using `Type.property` syntax, analogous to how `Type.method` works. I feel like if we did that, then it would obviate the need for explicit `property.get` or `property.set` for most native Swift uses, though maybe not ObjC interop uses.

I feel like if you don't have a way to fetch an unbound getter, you're missing the 90% case, which is constructs like:

  let textValues = textViews.map(.#text.get)

Agreed. I think there are a couple ways to approach that. We could resolve unbound property references contextually, so that Type.property gives you the getter in normal function context, or the lens in inout function context, and/or either allow implicit upconversion from lens to getter function or provide an explicit getter((inout T) -> inout U) -> T -> U adapter function.

How to differentiate these functions?

Doug talked about this some in his proposal.

John.

···

On Dec 27, 2015, at 4:54 PM, Wallacy <wallacyf@gmail.com> wrote:

class A{
    func someFunc(a: Int) -> Int{
        return 0;
    }
    func someFunc(a: Int) -> Double{
        return 0;
    }
    func someFunc(a: Double) -> Int{
        return 0;
    }
    func someFunc(a: Double) -> Double{
        return 0;
    }
   func someFunc(a: Int, b: Int) -> Int{
        return 0;
    }
}

Even with backticks would not be possible.

You may need to reference the method signature altogether.

var someA = A()
let fn1 = someA.#someFunc(a: Int) -> Int
let fn2 = someA.#someFunc(a: Int) -> Double
let fn3 = someA.#someFunc(a: Double) -> Int
let fn4 = someA.#someFunc(a: Double) -> Double

An operator at the beginning perhaps?

let fn1 = #someA.someFunc(a: Int) -> Int
let fn2 = #someA.someFunc(a: Int) -> Double
let fn3 = #someA.someFunc(a: Double) -> Int
let fn4 = #someA.someFunc(a: Double) -> Double

You may not need the full signature all the time, only necessary to differentiate.

extension A {
    func someOtherFunc(a: Int, b: Int) -> Int{
        return 0;
    }
    func someOtherFunc(){
    }
    func someOther(){
    }
}

let fn5 = someA.#someOtherFunc(a:, b:)
let fn6 = someA.#someOtherFunc()
let fn6 = someA.someOther

Another possibility:

let fn5 = #(someA.someOtherFunc(a:, b:))
let fn5 = @(someA.someOtherFunc(a:, b:))

Thus the parser can try to just focus on what's inside the #(...) or @(...)

Em dom, 27 de dez de 2015 às 22:27, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> escreveu:
> On Dec 27, 2015, at 4:15 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:
>
> On Dec 27, 2015, at 4:09 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:
>>> I’m a fan of good error recovery, but I don’t think it is a major concern here for two reasons:
>>>
>>> 1) The most common case in a method will lack a label, and "thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried reference.
>>> 2) A common case of accidentally completing a nullary call (thing.foo() vs thing.foo) will produce a type error. We already produce good QoI for an unapplied function - adding the inverse would be simple.
>>>
>>> Further, it will be uncommon *in general* to form a curried reference, so error recovery doesn’t have to be perfect in all the edge cases. As with other commenters, if it is at all possible to avoid the extra backticks, I’d really prefer that.
>>
>> The concern, I think, is that a messed-up normal call might look like a curried reference.
>>
>> My inclination would be to go the other way: if we get a syntax for this that we like, I think we should use it for *all* curried member references, and reject things like foo.bar in favor of foo.`bar`. The ability to write foo.bar for a method has always struck me as more clever than wise, to be honest.
>
> If you were to go that far, I’d suggest looking at this as a different version of the “." operator. If you resyntax curried to something else like (just a strawman, intentionally ugly syntax):
>
> foo.#bar
>
> Then you’d get a nice property that the plain old dot operator always has to be fully applied. This certainly would be a win for error recovery. Also, if you did this, you wouldn’t need the backticks from doug’s proposal either for things like:
>
> foo.#bar(param1:param2:)
>
> either.

Right. I really like this effect.

I’m not that bothered by requiring the backticks, especially because it generalizes well to non-member function references, which I’m not sure any sort of different-member-access syntax does.

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

Well, this works today:

let fn1: Int -> Int = someA.someFunc
let fn2: Int -> Double = someA.someFunc
let fn3: Double -> Int = someA.someFunc
let fn4: Double -> Double = someA.someFunc

In fact, this too works:

let fn1: (a: Int) -> Int = someA.someFunc
let fn2: (a: Int) -> Double = someA.someFunc
let fn3: (a: Double) -> Int = someA.someFunc
let fn4: (a: Double) -> Double = someA.someFunc

See the parameter name in the type? It could be used to disambiguate, but currently it is not taken into account: if you add a `someFunc` overload taking a different parameter name but the same types the above code becomes ambiguous.

···

Le 27 déc. 2015 à 19:54, Wallacy via swift-evolution <swift-evolution@swift.org> a écrit :

Even with backticks would not be possible.

You may need to reference the method signature altogether.

var someA = A()
let fn1 = someA.#someFunc(a: Int) -> Int
let fn2 = someA.#someFunc(a: Int) -> Double
let fn3 = someA.#someFunc(a: Double) -> Int
let fn4 = someA.#someFunc(a: Double) -> Double

An operator at the beginning perhaps?

let fn1 = #someA.someFunc(a: Int) -> Int
let fn2 = #someA.someFunc(a: Int) -> Double
let fn3 = #someA.someFunc(a: Double) -> Int
let fn4 = #someA.someFunc(a: Double) -> Double

--
Michel Fortin
https://michelf.ca

*"if you add a `someFunc` overload taking a different parameter name but
the same types the above code becomes ambiguous."*

Yes, I know, I forgot this example. Ironically that was the intent, but I
do not choose good examples.

I was just exploring the idea of having to display the full signature at
some point.

···

Em dom, 27 de dez de 2015 às 23:11, Michel Fortin <michel.fortin@michelf.ca> escreveu:

Le 27 déc. 2015 à 19:54, Wallacy via swift-evolution < > swift-evolution@swift.org> a écrit :
> Even with backticks would not be possible.
>
> You may need to reference the method signature altogether.
>
> var someA = A()
> let fn1 = someA.#someFunc(a: Int) -> Int
> let fn2 = someA.#someFunc(a: Int) -> Double
> let fn3 = someA.#someFunc(a: Double) -> Int
> let fn4 = someA.#someFunc(a: Double) -> Double
>
> An operator at the beginning perhaps?
>
> let fn1 = #someA.someFunc(a: Int) -> Int
> let fn2 = #someA.someFunc(a: Int) -> Double
> let fn3 = #someA.someFunc(a: Double) -> Int
> let fn4 = #someA.someFunc(a: Double) -> Double

Well, this works today:

let fn1: Int -> Int = someA.someFunc
let fn2: Int -> Double = someA.someFunc
let fn3: Double -> Int = someA.someFunc
let fn4: Double -> Double = someA.someFunc

In fact, this too works:

let fn1: (a: Int) -> Int = someA.someFunc
let fn2: (a: Int) -> Double = someA.someFunc
let fn3: (a: Double) -> Int = someA.someFunc
let fn4: (a: Double) -> Double = someA.someFunc

See the parameter name in the type? It could be used to disambiguate, but
currently it is not taken into account: if you add a `someFunc` overload
taking a different parameter name but the same types the above code becomes
ambiguous.

--
Michel Fortin
https://michelf.ca

I’m a fan of good error recovery, but I don’t think it is a major concern here for two reasons:

1) The most common case in a method will lack a label, and "thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried reference.
2) A common case of accidentally completing a nullary call (thing.foo() vs thing.foo) will produce a type error. We already produce good QoI for an unapplied function - adding the inverse would be simple.

Further, it will be uncommon *in general* to form a curried reference, so error recovery doesn’t have to be perfect in all the edge cases. As with other commenters, if it is at all possible to avoid the extra backticks, I’d really prefer that.

The concern, I think, is that a messed-up normal call might look like a curried reference.

My inclination would be to go the other way: if we get a syntax for this that we like, I think we should use it for *all* curried member references, and reject things like foo.bar in favor of foo.`bar`. The ability to write foo.bar for a method has always struck me as more clever than wise, to be honest.

If you were to go that far, I’d suggest looking at this as a different version of the “." operator. If you resyntax curried to something else like (just a strawman, intentionally ugly syntax):

   foo.#bar

Then you’d get a nice property that the plain old dot operator always has to be fully applied. This certainly would be a win for error recovery. Also, if you did this, you wouldn’t need the backticks from doug’s proposal either for things like:

   foo.#bar(param1:param2:)

either.

Right. I really like this effect.

I’m not that bothered by requiring the backticks, especially because it generalizes well to non-member function references, which I’m not sure any sort of different-member-access syntax does.

I’m bothered by it because it overloads backtick to mean two things: keywords-as-names, and annoying-sequences-of-tokens-as-names. Either use would be acceptable to me, but the fact that we have to support one nested inside the other makes it pretty nasty.

In the context of this proposal, I think of backticks as delimiters around a generalized name. It's a generalization of today's notion that it's an escaped identifier; more like an escaped name.

···

Sent from my iPhone

On Dec 27, 2015, at 8:34 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 27, 2015, at 4:27 PM, John McCall <rjmccall@apple.com> wrote:
On Dec 27, 2015, at 4:15 PM, Chris Lattner <clattner@apple.com> wrote:
On Dec 27, 2015, at 4:09 PM, John McCall <rjmccall@apple.com> wrote:

-Chris

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

"In the context of this proposal, I think of backticks as delimiters around
a generalized name. It's a generalization of today's notion that it's an
escaped identifier; more like an escaped name."

backticks are just a "hack", with the proposal 0001 (Allow (most) keywords
as argument labels), your proposal, we just will not see this feature
being used.

It's not just a matter of style, just does not seem natural.

Expand type annotation to "pick" the correct function, as I said before,
seems to me more natural. Or choose another symbol of course.

···

Em seg, 28 de dez de 2015 às 17:49, Douglas Gregor via swift-evolution < swift-evolution@swift.org> escreveu:

Sent from my iPhone

> On Dec 27, 2015, at 8:34 PM, Chris Lattner via swift-evolution < > swift-evolution@swift.org> wrote:
>
>
>>> On Dec 27, 2015, at 4:27 PM, John McCall <rjmccall@apple.com> wrote:
>>>
>>> On Dec 27, 2015, at 4:15 PM, Chris Lattner <clattner@apple.com> wrote:
>>>
>>> On Dec 27, 2015, at 4:09 PM, John McCall <rjmccall@apple.com> wrote:
>>>>> I’m a fan of good error recovery, but I don’t think it is a major
concern here for two reasons:
>>>>>
>>>>> 1) The most common case in a method will lack a label, and
"thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried
reference.
>>>>> 2) A common case of accidentally completing a nullary call
(thing.foo() vs thing.foo) will produce a type error. We already produce
good QoI for an unapplied function - adding the inverse would be simple.
>>>>>
>>>>> Further, it will be uncommon *in general* to form a curried
reference, so error recovery doesn’t have to be perfect in all the edge
cases. As with other commenters, if it is at all possible to avoid the
extra backticks, I’d really prefer that.
>>>>
>>>> The concern, I think, is that a messed-up normal call might look like
a curried reference.
>>>>
>>>> My inclination would be to go the other way: if we get a syntax for
this that we like, I think we should use it for *all* curried member
references, and reject things like foo.bar in favor of foo.`bar`. The
ability to write foo.bar for a method has always struck me as more clever
than wise, to be honest.
>>>
>>> If you were to go that far, I’d suggest looking at this as a different
version of the “." operator. If you resyntax curried to something else
like (just a strawman, intentionally ugly syntax):
>>>
>>> foo.#bar
>>>
>>> Then you’d get a nice property that the plain old dot operator always
has to be fully applied. This certainly would be a win for error
recovery. Also, if you did this, you wouldn’t need the backticks from
doug’s proposal either for things like:
>>>
>>> foo.#bar(param1:param2:)
>>>
>>> either.
>>
>> Right. I really like this effect.
>>
>> I’m not that bothered by requiring the backticks, especially because it
generalizes well to non-member function references, which I’m not sure any
sort of different-member-access syntax does.
>
> I’m bothered by it because it overloads backtick to mean two things:
keywords-as-names, and annoying-sequences-of-tokens-as-names. Either use
would be acceptable to me, but the fact that we have to support one nested
inside the other makes it pretty nasty.

In the context of this proposal, I think of backticks as delimiters around
a generalized name. It's a generalization of today's notion that it's an
escaped identifier; more like an escaped name.

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