Instead of _countTypeSequence(xs)
, what about
func measure<T...>(_ xs: T...) -> Int {
xs.#count // "#" already vaguely means "compiler wizardry" to me
}
or, a bit better IMHO, since it's T...
itself that dictates the number of elements, not any particular instance of T...
func measure<T...>(_ xs: T...) -> Int {
(T...).count
}
WRT to the spelling of _mapTypeSequence
, what about just using map
, but needing to provide a name for the particular type of whichever element you're working with in <>
?
func cut<T..., U...>(_ xs: T..., transform:(T...) -> U...) -> U... {
xs.map<T> { //
// Not sure if types should need the `.self` suffix here. I vote
// no, but I don't like that rule in regular Swift anyway.
switch T {
case Int: return $0 * 2
case String: return "Hello, " + $0
case View: return $0.padding(20)
case Equatable: return { other: T in $0 == other }
case CustomStringConvertible: return $0.description
// ...
case _: return "\(T.self)"
}
}
}
side note
(Wow, that's a lot of "return"s in there! Sure would be nice if the compiler could infer them in instances where a switch
is the only statement in a function or closure which is supposed to return something, and the case
in question only has a single expression...)
Setting aside the desire to keep this spelled different from the regular map
(which this technically does, since map
normally has two generic parameters, not one), the <>
part also provides a way to specify which type you're referring to if you've nested multiple maps with the same type sequence:
func convolutedExample <T..., U...> (xs: T..., ys: T...) -> U... {
xs.map<X> { x in
ys.map<Y> { y in
if X == Y { return "\(X.self) == \(Y.self), how boring..." }
// do whatever less boring stuff you want here
}
}
}
Anyway, moving on...
What about #
?
We could (though perhaps not "should") use those and …
— we could use *
or +
to denote “zero or one (respectively) or more of this type”, and postfix …
to denote “zero or more types”:
struct Foo <Type1: T…, Type2: (U, V…), Type3: (W…)+, Type4: (X+, Y…)*> {
var t1: Type1 // a heterogeneous sequence of types whose length is >= 0
var t2: Type2 // a heterogeneous sequence of types whose length is > 0
var t3: Type3 // a homogeneous sequence whose length is > 0 of heterogeneous type sequences whose lengths are >= 0
var t4: Type4 // a homogeneous sequence whose length is >= 0 of heterogeneous type sequences, each of which is a homogeneous type sequence whose length is > 0 followed by a heterogeneous type sequence whose length is >= 0
}
I must admit, it is a bit cryptic if you haven't been exposed to regular expressions, but it doesn't seem too hard to explain either (says the guy who first learned about *
and +
in this context many years ago). I mean, at some point I think we have to accept that code written about complex subjects might have complex syntax -- we just need to avoid making the syntax unnecessarily complex. That said, while this wouldn't bother me personally, I'm not the only person who uses Swift and I wouldn't be even a little bit surprised if someone comes up with a better way.