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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With