> On Apr 20, 2016, at 4:47 PM, Chris Lattner <clatt...@apple.com> wrote:
>
> On Apr 20, 2016, at 12:31 PM, David Owens II via swift-evolution
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> This is similar to another concern I raised with functions and being able to
>> essentially erase the function argument names and apply two different named
>> parameters just because their types match.
>>
>> It seems reasonable to me that you can go from (x: Int, y: Int) => (Int,
>> Int). However, going from (x: Int, y: Int) => (a: Int, b: Int) feels
>> somewhat odd. Yes, the types can obviously slot in there fine, but how much
>> importance do the labels for the types bring to the table?
>>
>> Similarly, should this (Int, Int) => (x: Int, y: Int) be allowed through an
>> implicit means? If so, then it's really just an intermediate step for (x:
>> Int, y: Int) => (a: Int, b: Int) working.
>
> I completely agree, I think it makes sense to convert from unlabeled to
> labeled (or back) but not from “labeled" to "differently labeled”.
>
>> So what matters more, type signatures or label names?
>>
>> Here's an example:
>>
>> typealias Functor = (left: Int, right: Int) -> Int
>>
>> func hi(x: Int, y: Int, fn: Functor) -> Int {
>> return fn(left: x, right: y)
>> }
>>
>> hi(1, y: 2, fn: +)
>> hi(1, y: 2, fn: *)
>>
>> If we say that the parameter names are indeed vital, then the above code
>> cannot work as the operators that match the type signature are defined as:
>>
>> public func +(lhs: Int, rhs: Int) -> Int
>>
>> Obviously, given a name to the parameter brings clarity and can be self
>> documenting, but if we want the above to work while making names just as
>> vital as the type signature, then we need to declare `Functor` as such:
>>
>> typealias Functor = (_ left: Int, _ right: Int) -> Int
>>
>> However, that's not even legal code today, and even if it were, is that
>> really better?
>
> I don’t think this follows, since operator parameters are always unlabeled.
> I suspect we don’t reject it, but I’d be in favor of rejecting:
>
> func +(lhs xyz: Int, rhs abc: Int) -> Int { }
So maybe I think about this incorrectly, but I always think of any parameter
without an explicit label to have one that is equal to the parameter name. So
these two functions signatures would be equivalent:
func sum1(lhs: Int, rhs: Int) -> Int
func sum2(lhs lhs: Int, rhs rhs: Int) -> Int
It’s only when you explicit “erase” the label where there is none:
func sum(_ lhs: Int, _ rhs: Int) -> Int
So back to the example above, it’s still somewhat odd that all of these are
valid:
hi(1, y: 2, fn: sum1)
hi(1, y: 2, fn: sum2)
hi(1, y: 2, fn: sum) // makes the most sense, no label to labeled promotion
But if we did reject the differently labeled version, that would mean that we
would need to declare the `Functor` above as:
typealias Functor = (Int, Int) -> Int
Is that better? I’m not terribly convinced that it is.
If `Functor` keeps the labels, I suspect it would just lead to additional
boiler-plate code that would look like:
typealias Functor = (left: Int, right: Int) -> Int
hi(1, y: 2, fn: { left, right in sum1(lhs: left, rhs: right) })
While it does seem technically correct, is that really the kind of code we want
in Swift?
-David
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution