> 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