[swift-evolution] Splat

Jonathan Tang jonathan.d.tang at gmail.com
Wed Feb 10 23:10:57 CST 2016

On Wed, Feb 10, 2016 at 8:37 PM, Brent Royal-Gordon <brent at architechies.com>

> > Ah, I see, at least for #1.  I'm assuming that to get the function that
> takes a tuple, you'd have to explicitly use the parameters: overload:
> Probably; otherwise this doesn't actually save the type checker much.
> There's a bit of a complication when talking about type signatures.
> Currently, the fact that a function operates on a tuple is embedded in our
> type syntax, and the parentheses around the argument list are optional and
> represent a tuple—`(Int, String) -> String` is equivalent to
> `TupleOfIntAndString -> String`. This might now need a change, or at least
> a clarification. For the purposes of this post, I'll say that `(Int,
> String) -> String` is the type of a function taking an Int and String,
> while `((Int, String)) -> String` is the type of a function taking a tuple.
> For the `concatenate(_:to:)` example, the original function has a
> signature of `(Int, String) -> String` (once argument labels are fully part
> of the name, which seems to be the trend). For each of the syntaxes I
> proposed, the type of this expression is `((Int, String)) -> String`:
>         concatenate(parameters:)
>         concatenate(_:to:).apply(to:)
>         concatenate(_:to: *)
> > let f = concatenate(_:to:).apply(to:)  // I assume this has type (Int,
> String) -> String
> > var g = f.apply(to:)  // Is this legal?  What's the type?
> That's an interesting question. Swift does not have 1-tuples, so unary
> functions might not have an `apply(to:)` method.
> > // This type signature is wrong, g takes an arbitrary argument
> list...but how do I write that?
> > func compose<Params, Intermediate, Result>(f: Intermediate -> Result ,
> g: Params -> Intermediate) -> Result {
> >   return { args in f.apply(to: g.apply(to: args)) }
> > }
> Without something along the lines of the `@splatting` annotation in a
> parameter list, it would not be possible to write a `compose(_:_:)`
> function which could operate on non-unary functions directly. Instead of
> writing `compose(f, g)`, you'd have to write `compose(f.apply, g.apply)`.
> If you think that's kind of ugly, I don't disagree.
> > // Here's a function that takes an Array of functions and applies them
> one after another...
> > // I don't really know where to start with this...the types of all of
> its arguments seem inexpressible
> > func composeMany</* ...arbitrary many intermediate params...
> */>(functions: [/* What type for arbitrary function? */]) {
> >   reduce(compose, functions, identity)
> > }
> Even with the current implicit splatting, this is impossible to express
> unless all functions have the same argument and return type. The generics
> system is simply not equipped to handle arbitrarily many generic types.
> > But then if it looks like a method, people are going to wonder why they
> can't pass it to a function or store it in a data-structure.
> I'm not sure why you think it can't be stored. I think it can.
Not the result of the splatting operation, but the splatting operation

let legal = [f, g)
let illegal = [f.apply, g.apply]   // But it certainly looks like an
expression that would normally be legal!

> > I saw that, briefly.  I hope that something like that makes it in, but
> it has similar issues with "What's the type signature of this operator, and
> if the only way it can exist is as compiler-supported syntax, how do we
> make it clear to users that this is a compiler language feature and not a
> first-class function call?"  IIRC the syntax suggested there made use of
> the #thisIsACompilerDirective naming convention.  I wonder if that might be
> appropriate here:
> >
> > f(#splat(tuple))
> > concatenate(_: #splat)
> >
> > The latter form also suggests a way this could be used for partial
> application:
> >
> > concatenate(2, #splat) returns a closure where the first argument is
> always 2, but any remaining arguments are pulled from the provided tuple.
> I don't really think # is a good fit here. I think it's best used in
> places where it's performing a relatively straightforward textual
> substitution; in the `concatenate(_: #splat)` case, that's not really
> what's being done here.
> (To tell the truth, in my head I imagine that when we finally get a macro
> system in Swift N, all macros are marked by a leading #. So I tend to get a
> little squeamish about # uses which draw heavily from context instead of
> relying on what you "pass" to them.)
The "..." syntax that's been batted around here looks fine to me as well.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160210/953cdd6c/attachment.html>

More information about the swift-evolution mailing list