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

T.J. Usiyan griotspeak at gmail.com
Wed Jan 27 00:36:12 CST 2016


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160127/af376423/attachment.html>

More information about the swift-evolution mailing list