> On May 31, 2016, at 9:22 PM, Brent Royal-Gordon <[email protected]> 
> wrote:
> 
> You know, I'm not a big fan of the `&` syntax people are pushing in the 
> `Any<>` thread,

Finally, a kindred soul!

> but if you ignore the Ceylon people begging for union types, I think a 
> sensible alternative meaning for `|` would be "all common supertypes of these 
> types". Then you could write:
> 
>       // Bottom here is the bottom type: the subtype of all types.
>       (Int, String, Bool).reduce(Bottom, combine: |)
> 
> And you'll end up with something like:
> 
>       Equatable & Hashable & _Reflectable
> 
> Which are the three protocols all of those types support. If they'd supported 
> no common protocols, it would've ended up with `Any`. (Interestingly, this is 
> arguably the same operation which should be used to determine the return 
> value of tuple subscripting.)

This is great for a tuple whose types are known at compile-time, but if you 
were building a variadic generic type your variadic generic parameters would 
probably be constrained by the same sorts of type-equality, conformance, and 
subtyping relations that your normal parameters are today. In that case, it 
would be useful to have a notion of "this function's generic constraints for T" 
and "that function's generic constraints for U" line up such that T is a 
subtype of U, hence we have a useful, compile-time-knowable lower bound for the 
argument type of a function designed to reduce the members of a variadic 
generic tuple. You could use this same machinery to convert the bounds into a 
generalized existential, allowing for a non-generic reducer.

> 
> Of course, nothing about having this feature *requires* that we use `&` and 
> `|`; that was just the inspiration for it.
> 
>> Other questions (inherent to any proposal) would be:
>> 
>> - How do we resolve the impedance mismatch between tuples and function 
>> argument lists? Is it even worth trying to resolve this mismatch, given that 
>> argument lists are intentionally not intended to mirror tuples?
> 
> As far as I know, tuples support a subset of argument list features. (For 
> instance, they don't support default values.) So if you splat a tuple into a 
> parameter list, the worst case is that you won't get to use features like 
> those.
> 
> One mismatch is that tuples barely care about their argument labels, while 
> parameter lists select overloads on them. My temptation would be to require 
> you to disambiguate with `(x:y:z)` syntax if you were splatting in an unclear 
> way.
> 
>       let triple = (0, 10, 2)
>       
>       stride(triple...)               // Illegal due to ambiguity; write one 
> of these:
>       stride(from:to:by:)(triple...)
>       stride(from:through:by:)(triple...)

I tested this - calling a function using the fully-qualified name works, but 
the argument list you provide still needs the parameter labels, which are 
redundant because they're part of the fully-qualified name. So you'd need: 
"stride(from:to:by:)(from:0, to:10, by: 2)". Removing this restriction would be 
a good first step.

Perhaps inout params of type T could be somehow passed as a pair (T, (T) -> 
()), where the first item is the input value and the second item is a writeback 
function representing the 'out' part of inout.

I've no ideas for default values.

> 
> One useful thing here is that the arity and types of a tuple are known at 
> compile time, so we can figure out ahead of time how to interpret the call. 
> That wouldn't be the case if you could splat arrays.
> 
> (Incidentally, we might want to offer a pseudo-failable initializer to create 
> a tuple from a sequence:
> 
>       if let triple = (Int, Int, Int)(intArray) {
>               return stride(from:to:by:)(triple...)
>       }
> 
> That would indirectly allow you to splat the contents of an array into a 
> parameter list.)
> 
>> - As you said, how do variadic generics work in the 0- and 1-member cases?
> 
> I don't think 0-tuples are a big deal, except in that there's no good 
> starting value for certain reductions. Adding a bottom type (as I did in the 
> `reduce` example above) would fix that.
> 
> 1-tuples are a bigger problem, because if you have a parameter like 
> `(Any...)`, you can't afford to interpret `((Int, String))` as `(Int, 
> String)`. It might be possible to support 1-tuples only in contexts where 
> you're using a variadic tuple, but I'm kind of skeptical of that idea.
> 
> Personally, I wish we'd just acknowledge `(SomeType)` (or maybe `(SomeType, 
> )`) as something different from `SomeType` and stop fretting. Sure, it's a 
> semi-useless degenerate case, but so are one-case `enum`s and 
> `Optional<Void>`s, and we don't ban those. Banning `T -> U` syntax has 
> already removed one of the sources of ambiguity here.

I agree that 1-ples would make a lot of things cleaner. Did any of the 
proposals on the topic ever get to the PR stage?

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to