[swift-evolution] History and future of Swift's parentheses

Jens Persson jens at bitcycle.com
Fri Jun 9 16:10:42 CDT 2017

The point of exercise 1 is to show that it is impossible (in Swift 4) to
write a generic function composition operator (or function) which works as
expected for any reasonable functions.
This was possible in Swift 3, but in Swift 4 it will only work for
functions with exactly one parameter. You'd have to special-case it for
every combination of parameter counts of f and g that it should be able to

The following program demonstrates how it can be done in Swift 3.1 and 3.2:

func compose<T, U, V>(_ g: @escaping (U) -> V, _ f: @escaping (T) -> U) ->
(T) -> V {
    return { x in g(f(x)) }
func sum(_ a: Int, _ b: Int) -> Int { return a + b }
func square(_ a: Int) -> Int { return a * a }
let squaredSum = compose(square, sum)
let result = squaredSum((3, 4)) // A bit unexepected with a tuple here but
ok ...
print(result) // 49
// Well, it worked, not flawlessly but we did manage to write
// a function composition function and we composed sum
// and square, and we could call it and get a correct result.

And this program demonstrates what happens if you try it in Swift 4:

func compose<T, U, V>(_ g: @escaping (U) -> V, _ f: @escaping (T) -> U) ->
(T) -> V {
    return { x in g(f(x)) }
func sum(_ a: Int, _ b: Int) -> Int { return a + b }
func square(_ a: Int) -> Int { return a * a }
// let squaredSum = compose(square, sum) // Error! (without the
compose-variant below)

// The error message is:
// Cannot convert value of type `(Int, Int) -> Int` to
// expected argument type `(_) -> _`

// That's it, it is simply not possible!

// You'd have to write special variants of the compose func for every
// of parameter counts! For example, in order to get this sum and square
// example working, this specific variant must be written:
func compose<T, U, V, W>(_ g: @escaping (V) -> W, _ f: @escaping (T, U) ->
V) -> (T, U) -> W {
    return { (x, y) in g(f(x, y)) }
// Now it will work:
let squaredSum = compose(square, sum)
// But only thanks to that awfully specific compose func variant ...
// We would have to write a lot more variants for it to be practically
usable on pretty much any common function.

I'm sure some will say:
"no regular developers use function composition anyway so why ..."
"It's not very swifty to use free functions and higher order functions like

My answer is that this is just a simple but telling example. The issue (as
I see it) exists in all situations involving generics and function types.

I'm a regular programmer and I like to be able to write basic, useful
It's no fun when the language forces you to write lots of specific variants
of your generic code.

I would feel less worried about the parentheses situation if the language
was going in a direction where you could see how this simple exercise would
be a no brainer.

Can Swift's parentheses-situation be sorted out before ABI stability?
Otherwise it would be a bit like if Swift had kept the special rule for the
first parameter, only much worse.


On Fri, Jun 9, 2017 at 7:17 PM, Gor Gyolchanyan <gor at gyolchanyan.com> wrote:

> Yes, except why would you need to define `((A, B)) -> C`?, If you need to
> pass a 2-element tuple into a function that takes two parameters - you can!
> If you want to pass two values into a function that  *looks* like it takes
> a single 2-element tuple - you can! Seems to me that the difference between
> `((A, B)) -> C` and `(A, B) -> C` is virtually non-existent. But keep in
> mind that this only works for bare tuples (the ones that can't have
> labels). Non-closure functions DO have labels, which is part of their
> signature, so this is a different story.
> On Jun 9, 2017, at 6:18 PM, Gwendal Roué <gwendal.roue at gmail.com> wrote:
> Le 9 juin 2017 à 17:12, Gor Gyolchanyan via swift-evolution <
> swift-evolution at swift.org> a écrit :
> So I wonder if any of you have had any thoughts about what Swift's
> parentheses-related future (or evolutionary baggage) will be?
> I really wish swift used the concept of tuples **exclusively** for all
> purposes that involve parentheses, as well as dividing tuples into two
> categories:
> - Bare tuples, which do not have labels.
> - Rich tuples, which do.
> As a consequence, here's a list of statements that would become true:
> - All functions take exactly one parameter, which is a tuple.
> - All closures (a.k.a. function pointers) take exactly one parameter,
> which is a bare tuple.
> - All functions return exactly one parameter, which is a tuple.
> - Pattern matching is done on a single bare tuple using a single bare
> tuple pattern.
> The currently ongoing proposal to make a single-element tuple auto-flatten
> would work extremely well with this idea, by making all these changes
> completely backward-compatible.
> If I have well understood, Swift has evolved away from this.
> If what you describe were true, added to the fact that there is no such
> thing as a one-element tuple in the language, then (A,B) -> C and ((A, B))
> -> C could not be distinguished, for the simple reason that ((A, B)) -> C
> could not be defined.
> For ((A, B)) -> C to be defined, we'd need a function that takes exactly
> one parameter, which is a tuple (your idea), whose single element is a
> tuple (oops, there is no single-valued tuples).
> No opinion here, just they way I have understood recent Swift history.
> Gwendal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170609/3f2e0cee/attachment.html>

More information about the swift-evolution mailing list