# Add nil-collapsing call expression

**URL:** <https://forums.swift.org/t/add-nil-collapsing-call-expression/14634>\
**Category:** Pitches\
**Created:** [July 20, 2018, 7:13pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634 "2018-07-20T19:13:04Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![dyl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dyl/32/2412_2.png) [@dyl](https://forums.swift.org/u/dyl)\
**Post date:** [July 20, 2018, 7:13pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/1 "2018-07-20T19:13:04Z")

</div>

Nil-coalescing expressions are ubiquitous in Swift. This pitch proposes an analogous expression for function calls nicknamed "nil-collapsing" (or "nil-cascading"). Instead of coalescing, it collapses the entire expression.

**What?**

> Note: I am unsure of the best syntax, so I will use ¿ as a placeholder.

While a nil-coalescing expression `a ?? b` reduces to `b` when `a` is `nil`, a nil-collapsing expression `f¿(...)` reduces to `nil` when any of the non-optional arguments of `f` are `nil`. To explain the behavior in more detail, we consider the following example:

```swift
func foo(_ x: Int, _ y: Int?) -> Int { return x + (y ?? 0) }

foo(nil, 2) // *type error*
foo¿(1, 2) // => 3 (no collapsing behavior)
foo¿(nil, 2) // => nil (call is collapsed, x is not optional)
foo¿(1, nil) // => 1

```

In effect, ¿ acts over a function type by adding an extra layer of Optional to all arguments. If any of the arguments which are _not_ already Optional are `nil`, then the call expression collapses.

I have attempted to implement this in user code, but failed for a couple of reasons:

- Propagating argument labels is finicky and fails for single parameter functions.
- It's not possible to check if a type is Optional (no type traits), so one ends up needing to implement overloads for every combination of Optional and non-Optional parameters for every possible tuple size (2-7, following with the standard library).

**Why?**

Consider the following motivating example:

```swift

// We have three functions which may or may not provide some resource.
func tryAcquireFoo() -> Foo? { /* snip */ }
func tryAcquireBar() -> Bar? { /* snip */ }
func tryAcquireBaz() -> Baz? { /* snip */ }

// And some function that requires a couple resources and 
// optionally requires one in order to produce something else.
func quxify(foo: Foo, bar: Bar, baz: Baz?) -> Qux { /* snip */ }

```

```swift

// To glue these all together we would have to do this:
func tryQuxify() -> Qux? {
  guard let foo = tryAcquireFoo() else {
    return nil
  }

  guard let bar = tryAcquireBar() else {
    return nil
  }

  let baz = tryAcquireBaz()

  return quxify(foo: foo, bar: bar, baz: baz)
}

// One could also use flatMap/compactMap, but that seems 
// very heavy and unwieldy. At the least, the above is clear.

```

```swift

// But by contrast, with a nil-collapsing operator,
// the intent can be expressed concisely and clearly:

func tryQuxify2() -> Qux? {
  return quxify¿(foo: acquireFoo(),
                 bar: acquireBar(),
                 baz: acquireBaz())
}

```

In short, a nil-collapse does what it says on the tin: it collapses an expression to nil. The term “nil-cascade” might be better though, in line with cascading behavior in a database.

---

<div class="post-metadata">

**Author:** ![rudkx](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rudkx/32/20610_2.png) [@rudkx](https://forums.swift.org/u/rudkx)\
**Post date:** [July 20, 2018, 7:28pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/2 "2018-07-20T19:28:35Z")

</div>

If `throw` becomes an expression of type `Never` and `Never` becomes a true bottom type, you'd be able to write this as:

```swift
   try? quixify(foo: acquireFoo() ?? throw CannotAcquireFoo, 
                bar: acquireBar() ?? throw CannotAcquireBar,
                baz: acquireBaz())

```

Of course you could also use plain `try` and handle the errors explicitly as well.

---

<div class="post-metadata">

**Author:** ![dyl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dyl/32/2412_2.png) [@dyl](https://forums.swift.org/u/dyl)\
**Post date:** [July 20, 2018, 7:56pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/3 "2018-07-20T19:56:04Z")

</div>

I like that. It feels a good bit more elegant than adding more syntax.

A couple questions:

1. Is there any penalty or overhead to using exceptions at runtime (apart from the cost of allocating the error)?

2. Is `throw` currently at all likely to become an expression? I'm out-of-the-loop as to any current or past discussions about that.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [July 20, 2018, 8:15pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/4 "2018-07-20T20:15:48Z")

</div>

> [@dyl](#):
>
> Is `throw` currently at all likely to become an expression?

This topic was discussed just last week by core team members: [Unwrap or Throw - Make the Safe Choice Easier - #3 by Joe\_Groff](https://forums.swift.org/t/unwrap-or-throw-make-the-safe-choice-easier/14453/3).

This idiom appears nice on the surface, but it doesn't interact well with the use case where the function itself is throwing. The `try? myFunc(optionalArg ?? throw MyError())` idiom swallows errors thrown by `myFunc` _in addition_ to those thrown when a `nil` argument is encountered. Proper support requires a feature that is orthogonal to the error system, just like optional chaining is orthogonal.

FWIW, the general structure underlying a solution to this problem is `Applicative`. Some programming languages include syntactic sugar called "idiom brackets" which addresses the use case for optionals, but also provides sugar for other `Applicative` types such as `Result`, `Future`, etc. I'm not sure exactly what this kind of syntactic sugar would look like in Swift but I would love to see it explored and added to the language someday.

---

<div class="post-metadata">

**Author:** ![dyl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dyl/32/2412_2.png) [@dyl](https://forums.swift.org/u/dyl)\
**Post date:** [July 20, 2018, 8:24pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/5 "2018-07-20T20:24:33Z")

</div>

Great timing, I had just now found that topic and started reading it.

That is a very good point. One way to get around it that isn't too horrible would be to separate building the argument list and applying the function to it. Tuple-splatting was removed (for what appear to be very good reasons), and propagating labels on named tuples can behave a little oddly, but something like this is possible:

```swift
let args = try? (foo: acquireFoo() ?? throw CannotAcquireFoo, 
                 bar: acquireBar() ?? throw CannotAcquireBar,
                 baz: acquireBaz())
do {
  try quixify <~ args // where <~ is some kind of splat/apply
} catch {
  // ...
}

```

This is less than great though. Maybe this kind of behavior is best left off for when we have variadic generics? It could possibly just be implemented as a higher-order function (modulo named parameter weirdness). There are some downsides to that too though. In the case where the function in question is an enum case initializer, you lose inference before the dot.

```swift
func foo() -> MyEnum {
  // this doesn't work, you have to write MyEnum.fizz
  return nilCollapsify(.fizz)(/* snip: arguments */) 
}

```

Somehow I don't think we're likely to see bananas, lenses and barbed wire in Swift any time soon 😅.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [July 20, 2018, 8:27pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/6 "2018-07-20T20:27:08Z")

</div>

Well, developing on the generalization of control flow as expressions discussed in that thread, you could perhaps do something like:

```swift
label: do {
  myFunc(optionalArg ?? break label)
}

```

or:

```swift
let optional = { myFunc(optionalArg ?? return nil) }()

```

that wouldn't trample on the error handling path. Idiom brackets are nice (though not as nice as extensible effects IMO), but for `Either`-like effects where there is no reentrance into the computation, I think the approach of control-flow-as-expression is more approachable.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [July 20, 2018, 8:53pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/7 "2018-07-20T20:53:04Z")

</div>

> [@Joe\_Groff](#):
>
> ```swift
> let optional = { myFunc(optionalArg ?? return nil) }()
> 
> ```
> 
> that wouldn't trample on the error handling path. Idiom brackets are nice (though not as nice as extensible effects IMO),

I would love to have extensible effects and forced to choose between them would agree with you. I have always thought of them as addressing slightly different use cases though. How might a solution to this use case look with extensible effects?

> [@Joe\_Groff](#):
>
> but for `Either` -like effects where there is no reentrance into the computation, I think the approach of control-flow-as-expression is more approachable.

That's not too bad but it seems a little on the clever side and also a little verbose for such a common use case. On the other hand, I can see the argument that general purpose sugar might be harder to understand than something more explicit like this. That makes me wonder if maybe optional does deserve the same kind of special case treatment here that it gets in many corners of the language.

If we do rely on the control-flow-as-expression approach I think that would increase the importance of coalescing optional in `try?` as discussed here: [Make try? + optional chain flattening work together](https://forums.swift.org/t/make-try-optional-chain-flattening-work-together/7415/1). This would improve the experience of the idiom in optional-returning functions (both non-throwing and throwing in cases where it's ok to flatten errors into `nil`). Without making `try?` coalesce optional the idiom would produce a double optional for optional-returning functions which is not what would intended or desired.

---

<div class="post-metadata">

**Author:** ![Jon\_Hull](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_hull/32/678_2.png) [@Jon\_Hull](https://forums.swift.org/u/Jon_Hull)\
**Post date:** [July 21, 2018, 2:43am UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/8 "2018-07-21T02:43:57Z")

</div>

A while back there was talk of using `?` after a function name to convert it to take one level higher of optional for each parameter, and of the return value as well... with it short circuiting and returning nil if any of the parameters were nil.

```
func foo(a: Int, b: String) -> Int

```

Which could be called as:

```
foo?(a: 10, b:nil) //has signature foo(a: Int?, b: String?) -> Int?

```

The worry was that both the short circuiting behavior and double optionals (e.g. Int??) would confuse people.

---

<div class="post-metadata">

**Author:** ![Daniel\_Resnick](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/daniel_resnick/32/480_2.png) [@Daniel\_Resnick](https://forums.swift.org/u/Daniel_Resnick)\
**Post date:** [July 21, 2018, 3:57am UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/9 "2018-07-21T03:57:48Z")

</div>

How about using optional pattern matching syntax:

```swift
func foo(_ x: Int, _ y: Int) -> Int {
    return x + y
}

let a: Int? = 5
let b: Int? = nil

foo(a?, a?) // => 10
foo(a?, b?) // => nil
foo(b?, a?) // => nil

```

---

<div class="post-metadata">

**Author:** ![dyl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dyl/32/2412_2.png) [@dyl](https://forums.swift.org/u/dyl)\
**Post date:** [July 23, 2018, 3:08pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/10 "2018-07-23T15:08:51Z")

</div>

That would create a couple of nice behaviors. I initially discarded it because I thought it would conflict with existing syntactic forms, but it doesn't seem like it would, actually.

1. You can collapse on _some_ rather than _all_ parameters.

```swift
let c: Int = 10

foo(c, a?) // => 15

```

1. This syntax would also intuitively generalize to operator expressions (which are conceptually sugared function calls).

```swift
a? + a? // => 10
a? + b? // => nil

```

This mixes nicely with coalescing:

```swift
a? + (b ?? 0) // => 5
b? + (a ?? 0) // => nil

```

This makes it quite succinct to indicate which parts of an expression are "required" for the computation, and which can be defaulted.

1. (Stretching) you could extend the same sugar to other expressions while preserving intuition, e.g.

```swift
let a: Int? = [1, 2, 3, nil]

for case let x? in a { print(x) }
// becomes
for x? in a { print(x) }

```

There was discussion about this in another thread I believe, it would be neat to see the same syntax work throughout the language. On the other hand, this is overloading `?` to mean a lot of related things. Not that it isn't already of course...

---

<div class="post-metadata">

**Author:** ![bob](https://avatars.discourse-cdn.com/v4/letter/b/ea666f/32.png) [@bob](https://forums.swift.org/u/bob)\
**Post date:** [July 25, 2018, 5:03am UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/11 "2018-07-25T05:03:00Z")

</div>

If someone wants to look through the mailing list archives, I'm sure you can find several mentions of this idea. Might be good to see where those conversations went before starting down this path again from scratch.

---

<div class="post-metadata">

**Author:** ![cherrywoods](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cherrywoods/32/2444_2.png) [@cherrywoods](https://forums.swift.org/u/cherrywoods)\
**Post date:** [July 25, 2018, 7:51am UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/12 "2018-07-25T07:51:15Z")

</div>

In regard to bob, I'm pretty sure someone has come up with what I want to say before, but personally, I currently don't have the time to crawl mailing lists 😬

I basically just want to say, that I don't find the current syntax demonstrated above (that can be collapsed a bit) not too bad at all:

```swift
func tryQuxify() -> Qux? {
  // You need the type notation at the end to avoid an "initializer for conditional binding must have Optional type" compiler error
 // There is currently another thread about this topic
  guard let foo = tryAcquireFoo(), 
        let bar = tryAcquireBar(), 
        let baz: Baz = tryAcquireBaz() else { return nil }
  return quxify(foo: foo, bar: bar, baz: baz)
}

```

This code seems "natural" to me in swift.

Also this code seems not to be significantly longer than what is described above.

Sure, you can get nil collapsing inside one line, e.g. with `<*>` (see: Haskell, Applicative), but to me the above code also feels more intuitive (coming from the context of imperative languages) than a long chain of applications. If there is a nice and intuitive way to write such a chain of applications (in contrast to the basic`<*>` notation which isn't intuitive for most people I know), I think it would be a great idea to have it in swift, not only for Optional, but the whole concept might be to abstract...?

I think if someone has some experience in swift, the above code is well understandable. The other solutions above aren't bad at all and also not too hard to read (at least to me), but from my point of view, they seem to use less "basic" concepts of the language. This is IMO an important point, since nil collapsing is something you stumble upon relatively quickly when learning the language and getting introduced to optionals.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [July 25, 2018, 3:28pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/13 "2018-07-25T15:28:31Z")

</div>

I wrote a thread about this here:

> [@Optional Argument Chaining](https://forums.swift.org/t/optional-argument-chaining/7237/27):
>
> It would definitely be nice to make "Optional" sugar work for non-"Optional" types! (I think the goal for "async"/"await" is to make it work for any continuation, so it's basically Haskell "do" notation for Swift!) I'm not sure the "Unwrappable" protocol can handle many of the examples I mentioned (accumulative errors, parallelism), though I wonder if it could be designed differently to do so. The applicative structure requires just 2 functions[1]: &nbsp;&nbsp;&nbsp;&nbsp;protocol Applicative\<A\>: Functor\<A\> { &nbsp;&nbsp;&nbsp;…

The pseudo-code imagines what idiom brackets may look like in Swift.

Optionals would work as proposed in this thread:

```swift
var id: Int?
var email: String?
User(|id: id, email: email|)
// Optional<User>

```

Throws could accumulate errors somehow.

```swift
func validate(id: Int) throws -> Int {
  if id < 1 { throw ValidationError.invalidId }
  return id
}
func validate(email: String) throws -> Int {
  if email.index(of: "@") == nil { throw ValidationError.invalidEmail }
  return email
}
User(|id: try validate(id: id), email: try validate(email: email)|)
// accumulates multiple errors in Result<User, [Error]>,
// or rethrows some accumulated error type

```

Async/await could optimize for parallelization:

```swift
User(|id: await fetchId(), email: await fetchEmail()|)
// dispatches "fetchId" and "fetchEmail" concurrently

```

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [July 25, 2018, 3:50pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/14 "2018-07-25T15:50:36Z")

</div>

> [@stephencelis](#):
>
> The pseudo-code imagines what idiom brackets may look like in Swift.

I must have forgotten about your previous post and the imagined syntax. I like it! 🙂 If we want to push this forward before higher-kinded types are available maybe we could explore a design for idiom brackets that uses an `@applicative` attribute, similar to where `@dynamicMemberLookup` landed.

---

<div class="post-metadata">

**Author:** ![amnykon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/amnykon/32/5803_2.png) [@amnykon](https://forums.swift.org/u/amnykon)\
**Post date:** [February 28, 2019, 4:46am UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/15 "2019-02-28T04:46:34Z")

</div>

I really like the syntax sugar of foo(a?, b?). It falls inline with the forced unwrap operator: foo(a!, b!)

The main issue is short circuiting. By convention, I don't use functions with side effects as direct inputs to other functions, so I feel we should short circuit is preferred.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [February 28, 2019, 2:11pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/16 "2019-02-28T14:11:34Z")

</div>

Isn't the canonical way to do this today `Optional.map`?

```
func foo(_ x: Int, _ y: Int?) -> Int { return x + (y ?? 0) }

let x: Int? = nil
let y: Int? = 3

y.map { foo($0, 3) } // == .some(6)
x.map { foo($0, 3) } // == nil

tryAcquireFoo().map { foo in tryAcquireBar().map { bar in tryAcquireBaz().map { baz in quxify(foo, bar, baz) } } }

```

---

<div class="post-metadata">

**Author:** ![amnykon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/amnykon/32/5803_2.png) [@amnykon](https://forums.swift.org/u/amnykon)\
**Post date:** [February 28, 2019, 3:42pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/17 "2019-02-28T15:42:31Z")

</div>

Map does work, however it is not as clean and is more difficult to understand if there are multiple optionals. It also nests the optionals, which requires an as? to unwrap the Int??? to an Int? if there are more then 1 maps.

```
let x: Int? = 1
let y: Int? = 2
let z: Int? = 3

func foo (_ values: Int...) -> Int {
    return 6
}

//canonical way
let s = x.map { x in y.map { y in z.map { z in foo(x, y, z)}}} as? Int

//pitched way
let s = foo(x?, y?, z?)

```

---

<div class="post-metadata">

**Author:** ![cukr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cukr/32/889_2.png) [@cukr](https://forums.swift.org/u/cukr)\
**Post date:** [February 28, 2019, 3:56pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/18 "2019-02-28T15:56:18Z")

</div>

> [@amnykon](#):
>
> It also nests the optionals, which requires an as? to unwrap the Int??? to an Int? if there are more then 1 maps.

If you want to flatten the nested optionals you use flatMap instead of map

```swift
let s = x.flatMap { x in y.flatMap { y in z.map { z in foo(z, y, z) }}}

```

Still not great.

---

<div class="post-metadata">

**Author:** ![mattpolzin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattpolzin/32/6041_2.png) [@mattpolzin](https://forums.swift.org/u/mattpolzin)\
**Post date:** [February 28, 2019, 5:01pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/19 "2019-02-28T17:01:20Z")

</div>

This seems like a “zip with” operation on Optional to me. Not provided by the standard library right now, but I’ve written these functions for myself before.

```
zip(optionalA, optionalB) { foo($0, $1) }

```

This evaluates to nil if either of its inputs are nil or the result of calling foo otherwise.

Not entirely sure this is an appropriate use of the name “zip” but I have not found better naming before and it feels analogous to zipping on an array in the monadic sense.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [February 28, 2019, 5:37pm UTC](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634/20 "2019-02-28T17:37:07Z")

</div>

> [@mattpolzin](#):
>
> This seems like a “zip with” operation on Optional to me.

Could even be variadic so that you could write:

```
zip(optionalA, optionalB, optionalC) { args in foo(args[0], args[1], args[2]) }

```

[Next page](https://forums.swift.org/t/add-nil-collapsing-call-expression/14634.md?page=2)
