In javascript we use IIFEs a lot. Something like
(function() {
...do stuff to avoid dirtying scope.
}());
There are closures in Swift, and functions are first class objects. My question is: are there equivalent IIFEs in Swift?
An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.
IIFEs are very useful because they don't pollute the global object, and they are a simple way to isolate variables declarations. An Immediately-invoked Function Expression (IIFE for friends) is a way to execute functions immediately, as soon as they are created.
An Immediate-Invoked Function Expression (IIFE) is a function that is executed instantly after it's defined. This pattern has been used to alias global variables, make variables and functions private and to ensure asynchronous code in loops are executed correctly.
IIFE (Immediately Invokable Function Expression) is a important concept in JavaScript. it is a commonly used Design Pattern which is used to wrap set of variables and functions which cannot be accessed outside the enclosed scope.
The accepted answer here is misleading—there's an easier and more elegant manner in which to create an immediately-invoked closure expression (IICE).
For all of the details and variances of syntax, see the Apple Swift Documentation for closures. For a simple demo, see this:
let dateString: NSString = { date in
let timestampFormatter = NSDateFormatter()
timestampFormatter.dateStyle = .MediumStyle
timestampFormatter.timeStyle = .MediumStyle
return timestampFormatter.stringFromDate(date)
}(NSDate())
You can achieve a similar effect using closures, sure:
func iife( f : () -> () ) {
f()
}
And then say
iffe {
// my code here
}
If all you truly need is a scope, while Swift does not support the use of {..} as a "scoping operator", you can always do
if 1 == 1 {
// oh, look, a scope :-)
}
as a less fancy way to achieve the same effect. If you're trying to use RAII patterns, you will need to either rely on ARC to cleanup for you, or use a closure though
if true {
// should also work instead of if 1 == 1
}
Here's another example of a Swift immediately-invoked closure expression (IICE) - which I pronounce as "Icky" (in a nod to JavaScript's IIFE, which is pronounced "Iffy" - http://benalman.com/news/2010/11/immediately-invoked-function-expression/)
var player:AVAudioPlayer = {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = NSURL(fileURLWithPath: path)
let p = try! AVAudioPlayer(contentsOf: url as URL)
p.volume = 0.3
p.prepareToPlay()
return p
}()
And if you use the lazy
modifier, you are then allowed to access self
.
From the Swift Language Guide: "Lazy properties are useful when the initial value for a property is dependent on outside factors whose values are not known until after an instance’s initialization is complete. Lazy properties are also useful when the initial value for a property requires complex or computationally expensive setup that should not be performed unless or until it is needed."
let startVolume:Float = 0.3
lazy var player:AVAudioPlayer = {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = NSURL(fileURLWithPath: path)
let p = try! AVAudioPlayer(contentsOf: url as URL)
p.volume = self.startVolume
p.prepareToPlay()
return p
}()
Also see "Setting a Default Property Value with a Closure or Function" in the Swift Language Guide.
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