[swift-evolution] Proposal: Remove implicit tuple splat behavior from function applications

Jens Persson jens at bitcycle.com
Wed Jan 27 01:44:15 CST 2016

+-0. I saw, in my dreams, many "different parts" of the language, like
pattern matching, function argument- & parameter lists, and tuples, all
just being one and the same simple yet powerful unifying concept ...
:´ /

On Wed, Jan 27, 2016 at 7:38 AM, Jacob Bandes-Storch via swift-evolution <
swift-evolution at swift.org> wrote:

> +1 from me as well. I don't think I've ever used this feature on purpose.
> I look forward to future discussions about splatting, especially as they
> relate to variadic functions.
> On Tue, Jan 26, 2016 at 10:36 PM, T.J. Usiyan via swift-evolution <
> swift-evolution at swift.org> wrote:
>> +1
>> I like the feature quite a bit but avoid it as a result of the naming
>> concerns. If removing this feature can help improve the type checker, the
>> trade is worthwhile, IMO.
>> On Wed, Jan 27, 2016 at 1:23 AM, Chris Lattner via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>> For discussion: comments appreciated!
>>> Remove implicit tuple splat behavior from function applications
>>>    - Proposal: SE-
>>>    <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md>
>>>    TBD
>>>    - Author(s): Chris Lattner
>>>    - Status: *Awaiting review*
>>>    - Review manager: TBD
>>> <https://github.com/apple/swift-evolution#introduction>Introduction
>>> Function calls (which include several syntactic forms that apply an
>>> argument list to something of function type) currently have a dual nature
>>> in Swift.  Given something like:
>>> func foo(a : Int, b : Int) {}
>>> You can call it either with with the typical syntactic form that passes
>>> arguments to each of its parameters:
>>> foo(42, b : 17)
>>> or you can take advantage of a little-known feature to pass an entire
>>> argument list as a single value (of tuple type):
>>> let x = (1, b: 2)
>>> foo(x)
>>> This proposal recommends removing the later form, which I affectionately
>>> refer to as the “tuple splat” form.  This feature is purely a sugar
>>> feature, it does not provide any expressive ability beyond passing the
>>> parameters manually.
>>> Swift-evolution thread: TBD
>>> <https://github.com/apple/swift-evolution#motivation>Motivation
>>> This behavior is cute, precedented in other functional languages, and
>>> has some advantages, but it also has several major disadvantages, which are
>>> all related to its syntactic form.
>>> * A call to foo(x) looks like a call to an overloaded version of foo,
>>> both to the compiler and to the human who maintains the code.  This is
>>> extremely confusing if you don’t know the feature exists.
>>> * There are real ambiguities in the syntax, e.g. involving Any arguments
>>> and situations where you want to pass a tuple value as a single parameter.
>>> * The current implementation has a ton of implementation bugs - it
>>> doesn’t work reliably.
>>> * The current implementation adds complexity to the type checker,
>>> slowing it down and adding maintenance burden.
>>> * The current implementation doesn’t work the way we would want a tuple
>>> splat operation to work.  For example, arguably, you should be able to call
>>> foo with:
>>> func bar() -> (Int, Int) { … }
>>> foo(bar())
>>> … but this is not allowed, since tuple labels are required to line up.
>>> You have to write:
>>> func bar() -> (Int, b: Int)  { … }
>>> foo(bar())
>>> This makes this feature very difficult to use in practice, because you
>>> have to _’ize a lot of parameters (violating naming conventions), perform
>>> manual shuffling (defeating the sugar benefits of the feature), or add
>>> parameter labels to the result of functions (which leads to odd tying
>>> between callers and callees).
>>> The root problem here is that we use exactly the same syntax for both
>>> forms of function application.  If the two forms were differentiated (an
>>> option considered in “alternatives considered” below) then some of these
>>> problems would be defined away.
>>> From a historical perspective, the tuple splat form of function
>>> application dates back to very early Swift design (probably introduced in
>>> 2010, but possibly 2011) where all function application was of a single
>>> value to a function type.  For a large number of reasons (including default
>>> arguments, variadic arguments, labels, etc) we have completely abandoned
>>> this model, but we never came back to reevaluating the tuple splat behavior.
>>> If we didn’t already have this feature, we would not add it to Swift 3
>>> (at least in its current form).
>>> <https://github.com/apple/swift-evolution#proposed-solution>Proposed
>>> solution
>>> The proposed solution is simple, we should just remove this feature from
>>> the Swift 3 compiler.  Ideally we would deprecate it in the Swift 2.2
>>> compiler and remove it in Swift 3.  However, if there isn’t time to get the
>>> deprecation into Swift 2.2, the author believes it would be perfectly fine
>>> to just remove it in Swift 3 (with a fixit + migration help of course).
>>> One of the interesting aspect of this feature is that some of the people
>>> we’ve spoken to are very fond of it.  However, when pressed, they admit
>>> that they are not actually using it widely in their code, or if they
>>> are using it, they are abusing naming conventions (distorting their code)
>>> in order to use it.  This doesn’t seem like a positive contribution - this
>>> seems like a “clever” feature, not a practical one.
>>> <https://github.com/apple/swift-evolution#detailed-design>Detailed
>>> design
>>> The design is straight-forward.  In the Swift 3 time frame, we continue
>>> to parse and type check these expressions as we have so far, but produce an
>>> error + fixit hint when it is the tuple splat form.  The migrator would
>>> auto-apply the fixit hint as it does for other cases.
>>> <https://github.com/apple/swift-evolution#impact-on-existing-code>Impact
>>> on existing code
>>> Any code that uses this feature will have to move to the traditional
>>> form.  In the case of the example above, this means rewriting the code from:
>>> foo(x)
>>> into a form like this:
>>> foo(x.0, x.b)
>>> In the case where “x” is a complex expression, a temporary variable will
>>> need to be introduced.  We believe that compiler fixits can handle the
>>> simple cases directly and that this extension is not widely used.
>>> <https://github.com/apple/swift-evolution#alternatives-considered>Alternatives
>>> considered
>>> The major problem with this feature is that it was not well considered
>>> and implemented properly (owing to its very old age, it has just been kept
>>> limping along).  The alternative then is to actually design a proper
>>> feature to support this.  Since the implicitness and syntactic ambiguity
>>> with normal function application is the problem, the solution is to
>>> introduce an explicit syntactic form to represent this.  For example,
>>> something like this could address the problems we have:
>>> foo(*x)    // NOT a serious syntax proposal
>>> However, actually designing this feature would be a non-trivial effort
>>> not core to the Swift 3 mission:
>>> * It is a pure-sugar feature, and therefore low priority.
>>> * We don’t have an obvious sigil to use.  “prefix-star” should be kept
>>> as unused for now in case we want to use it to refer to memory-related
>>> operations in the future.
>>> * Making the tuple splat operation great requires more than just fixing
>>> the syntactic ambiguities we have, it would require re-evaluating the
>>> semantics of the operation (e.g. in light of parameter labels, varargs and
>>> other features).
>>> If there is serious interest in pursuing this as a concept, we should do
>>> it as a follow-on proposal to this one.  If a good design emerges, we can
>>> evaluate that design based on its merits.
>>> The final alternative is that we could leave the feature in the
>>> compiler.  However, that means living with its complexity “forever” or
>>> breaking code in the Swift 4 timeframe.  It would be preferable to tackle
>>> this breakage in the Swift 3 timeframe, since we know that migration will
>>> already be needed then.
>>> -Chris
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

bitCycle AB | Smedjegatan 12 | 742 32 Östhammar | Sweden
Phone: +46-73-753 24 62
E-mail: jens at bitcycle.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160127/7f01c7df/attachment.html>

More information about the swift-evolution mailing list