Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't extend closure in Swift?

Flush with excitement from extending Bool, I thought it would be fun to extend closures in Swift (we did this with no fuss at all in Smalltalk, so why not?).

Here's my playground:

typealias NiladicClosure = () -> ()

extension NiladicClosure {
    var theAnswerToLife:Int {
        return 42
    }
}

let block:NiladicClosure = {}

block.theAnswerToLife

It doesn't work, saying that NiladicClosure does not have a member named 'theAnswerToLife'. Looking in the console, I get a bit more information:

Playground execution failed: /var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/33726/playground119.swift:3:1: error: non-nominal type 'NiladicClosure' cannot be extended
extension NiladicClosure {
^         ~~~~~~~~~~~~~~

What is a non-nominal type? Is there a pattern/workaround?

Other similar questions predated Swift 2, also were specific enough that people offered workarounds to the specific extension. I'm interested in whether Swift closures are first class objects that I can add additional behavior to, like other things in Swift.

like image 495
Travis Griggs Avatar asked Jun 18 '15 21:06

Travis Griggs


1 Answers

What is a non-nominal type?

A nominal type is a type with an explicit name. A non-nominal type is a type without such a name, like () -> (). Compound types, including closures and tuples (such as (Int, String)) cannot be extended.

Is there a pattern/workaround?

You could use composition instead of extensions, perhaps using Swift 2's new protocol features:

typealias NiladicClosure = () -> ()

protocol NiladicClosureProtocol {
    var someClosure : NiladicClosure? {get}
}

protocol SorryForTheInconvenience {
    var theAnswerToLife : Int {get}
}

extension SorryForTheInconvenience {
    var theAnswerToLife : Int {
        return 42
    }
}

struct SomethingAwesome : NiladicClosureProtocol, SorryForTheInconvenience {
    var someClosure : NiladicClosure?
}

let foo = SomethingAwesome()
foo.theAnswerToLife // 42
like image 152
Aaron Brager Avatar answered Sep 21 '22 07:09

Aaron Brager