how to extend optional chaining for all types

Matthew Butterick

If we have optional values foo and bar, Swift will allow us to write:

foo?.doSomething(bar)

Which will evaluate to nil if foo is nil. But it will not let us write:

foo?.doSomething(bar?)

That is, optional chaining only works on the arguments outside a function call, not inside the argument list. (The reasons for this limitation are unclear, but here we are.)

Suppose I want to write an apply function that lets me move things into the jurisidiction of optional chaining, like so:

bar?.apply { foo?.doSomething($0) }

Here, apply is a generic function that takes one argument (in this case bar) and then executes the closure. So if either foo or bar is nil, the expression will be nil.

Here's what I’ve tried:

public protocol HasApply {}
extension HasApply {
    public func apply<T>(_ f : (Self) -> T) -> T {
        f(self)
    }
}

That’s fine as far as it goes. But to make it work, I still have to explicitly apply the protocol to the types I care about:

extension Int : HasApply {}

OK, that makes it work with Int. But I don’t want to copy & paste for every type. So I try this:

extension AnyObject : HasApply {}

No, that won’t work: the error is Non-nominal type 'AnyObject' cannot be extended.

Hence the question: is there no way to make this generic function work as a protocol method?

Sweeper

is there no way to make this generic function work as a protocol method?

No, you must "explicitly apply the protocol to the types I care about".

However, you are in fact reinventing the wheel. This is the use case of flatMap/map. If both foo and bar are optional, you can write:

bar.flatMap { foo?.doSomething($0) }

Note the lack of ? after bar. You are calling flatMap on Optional, rather than bar's type. If doSomething returns T, the above expression will return T?.

If only bar is optional, use map:

bar.map { foo.doSomething($0) }

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Extend all types in Swift?

From Dev

Extend all number types in Swift

From Dev

How to know where Optional Chaining is breaking?

From Java

How to use optional chaining with array in Typescript?

From Dev

How to extend Hapi types [Typescript]

From Java

How to use optional chaining in Node.js 12

From Java

How to enable optional chaining with Create React App and TypeScript

From Dev

How to use optional chaining while searching through a dictionary in swift?

From Java

Optional chaining (?.) in nashorn

From Dev

Optional Chaining returning an Int

From Dev

Swift 3.0 Optional Chaining

From Dev

Optional Chaining in JavaScript

From Dev

swift optional chaining with cast

From Dev

Optional Chaining Not Working As Expected

From Dev

Optional chaining with Swift strings

From Dev

Chaining Optional.orElseThrow

From Dev

Optional chaining and Array in swift

From Dev

Optional chaining for constructor calls?

From Dev

How to port from java.util.Optional method call chaining to Guava Optional?

From Dev

Chaining iterators of different types

From Dev

Optional chaining not working for optional protocol requirements

From Dev

Is there an equivalent to optional chaining with arithmetic operators?

From Dev

dynamicType of optional chaining not the same as assignment

From Dev

Optional.ofNullable and method chaining

From Dev

Optional Chaining or ternary expression in Swift?

From Dev

How can we extend all enum type?

From Dev

How to extend partition to all unallocated space in a VPS?

From Dev

How to extend the Serializable interface to all sub Class?

From Dev

How to implement optional chaining / checking nested object properties using VanillaJS or Lodash

Related Related

HotTag

Archive