I think the important thing to remember is that the label check is intended to
prevent cases like this:
let a:(left:Int, right:Int) = (1, 2)
var b:(right:Int, left:Int) = a
While the two tuples are compatible by type, the meaning of the values may
differ due to the different labels; in this case the values are represented in
a different order that a developer should have to explicitly reverse to ensure
they aren’t making a mistake, or they could represent radically different
concepts altogether.
It’s certainly annoying when the labels are only different due to minor
differences, but the compiler doesn’t know that. So yeah, I think that in any
case where there are external labels that differ a warning should be raised;
this comes down to being able to later ignore types of warnings, which could
avoid the boiler-plate in future.
The alternative would be if we had some syntax for mapping parameters more
cleanly, for example:
hi(1, y: 2, fn: sum1 where left = lhs, right = rhs)
Or something along those lines anyway?
> On 21 Apr 2016, at 06:18, David Owens II via swift-evolution
> <[email protected]> wrote:
>
>>
>> On Apr 20, 2016, at 4:47 PM, Chris Lattner <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> On Apr 20, 2016, at 12:31 PM, David Owens II via swift-evolution
>> <[email protected] <mailto:[email protected]>> 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
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution