Treehouse Intermediate Course - Part 11 (Closures 2)
So, as expected, I had to miss two days. But I'm back! I have a bit of time this evening to carry on with closures - certainly, completing the first part of the Treehouse track. So far, it's all been fine and I haven't found any issues. OK, let's go!
Start Time - 18:56
Start Time - 18:56
func gameCounter() -> IntegerFunction {
var localCounter = 0
func increment(_ i: Int) {
print("Integer passed in: \(i)")
}
return increment
}
So just a reminder of scope. The localCounter variable is local as it is inside the body of the method; it can't be used outside that function.
*Paused at 19:03 (not able to concentrate - need to come back to this to take it in properly.)
*Continued at 20:11
The increment function now has localCounter += inside it. It can use the localCounter var as it is defined outside of its scope. It can also capture its state - its state of being a variable.
If we call the method with 1 again, then the value is now 2! We assigned it to a constant. So we capture and maintain it as a constant.
So increment is not the closure; counter is. So each constant created that runs the counter function has its own state. It maintains its own value.
OK, some of that was confusing and nonsensical and honestly, quite repetitive! No matter, I'm continuing as I don't see the point of going over it more.
*Paused at 20:20 then stopped just after! (16 minutes so far)
Too many interruptions! Going to leave this for now as 'saved', then do as part of a proper entry tomorrow!
Continued at 10:41 (next day!)
So I was a bit distracted yesterday. But looking over it, it was pretty simple! Mostly about scope and the use of a function within another function. I got 5 out of 5 on the quiz, so have clearly picked up what I need to at this point. The next bit is actually called 'A Quick Recap', so perfect to ensure I'm ready for the inevitably trickier bits!
Recap
Functions are FIRST CLASS citizens. This means they can take on native types and acquire the basic functionality.
You can assign functions to constants. The constant then has that functionality to use.
You can use functions as INPUTS to other functions.
You can use functions as RETURN types.
Nested functions - capture or close over variables/constants - this links most to closures
A closure is a combination of a function and an environment of CAPTURED variables.
Closure/closure expressions - different implementations but both called closures!
Syntax for closure expression -

So the map is an in built function.
The point is that the above is cumbersome. Closure expressions makes the whole thing nicer and easier!
*5 minute pause.
Closure Expression Syntax
This is what I need!!
So here is the example -
Am pausing Pasan just to break this down. So you need the usual parentheses for after map, then the pair of curly brackets. Inside the curly brackets is where the closure expression goes. It has the inputs, then return, then the 'in return' keywords are used, then what is actually happening: value times 3.
That is clearly quicker but still hard to read!
So I was a bit distracted yesterday. But looking over it, it was pretty simple! Mostly about scope and the use of a function within another function. I got 5 out of 5 on the quiz, so have clearly picked up what I need to at this point. The next bit is actually called 'A Quick Recap', so perfect to ensure I'm ready for the inevitably trickier bits!
Recap
Functions are FIRST CLASS citizens. This means they can take on native types and acquire the basic functionality.
You can assign functions to constants. The constant then has that functionality to use.
You can use functions as INPUTS to other functions.
You can use functions as RETURN types.
Nested functions - capture or close over variables/constants - this links most to closures
A closure is a combination of a function and an environment of CAPTURED variables.
Closure/closure expressions - different implementations but both called closures!
Syntax for closure expression -

func double(_ value: Int) -> Int {
return value * 2
}
double(4)
let doubleFunction = double
doubleFunction(6)
let numArray = [1, 2, 3, 4]
let doubledNumbers = numArray.map(doubleFunction)
So the map is an in built function.
The point is that the above is cumbersome. Closure expressions makes the whole thing nicer and easier!
*5 minute pause.
Closure Expression Syntax
This is what I need!!
So here is the example -
let tripledNumbers = numArray.map({(value: Int) -> Int in return value * 3})
Am pausing Pasan just to break this down. So you need the usual parentheses for after map, then the pair of curly brackets. Inside the curly brackets is where the closure expression goes. It has the inputs, then return, then the 'in return' keywords are used, then what is actually happening: value times 3.
That is clearly quicker but still hard to read!
let tripledNumbers = numArray.map({(value: Int) -> Int in
return value * 3
})
That looks more like a function in terms of layout!
Rule number 1 - define the closure inline
So rather than doing separate functions etc, it can all be done at once
Rule number 2 - inferring type from context
In our example, swift can infer that we are using ints! So we don't actually need the Int declaration...
let tripledNumbers2 = numArray.map({value in return value * 3})
That has the exact same outcome without having to specify Int or the -> etc. Nice!
The compiler infers it will be an integer because of the fact we are using numArray. Value is just local constant that we are assigning the integer value to. It is an argument label without the type being specified.
So we rarely need to write it in the full form - like in tripledNumbers. So it is a balance between conciseness and readability. That's fair enough.
Rule Number 3 - implicit returns from single expression closures
let tripledNumbers3 = numArray.map({value in value * 3})
Simpler still - return not needed as the compiler infers that it is a single expression, so we want to return that value. Cool!
Paused at 11:10 (24 minutes so far today; 40 minutes so far in the entry!)
Resumed at 15:37
Back!
Closure Expression Shorthand
However confusing it can be to make code very concise, it's useful to see how and why as OTHER people's code can be using this!
Rule Number 4 - using shorthand names
*Paused for a few minutes as internet not working...
This is what I predict will be next!
Resumed at 15:37
Back!
Closure Expression Shorthand
However confusing it can be to make code very concise, it's useful to see how and why as OTHER people's code can be using this!
Rule Number 4 - using shorthand names
*Paused for a few minutes as internet not working...
This is what I predict will be next!
let tripledNumber4 = numArray.map({$0 * 3})
Yes that seems to work! OK back to the rule as internet now working.
The rule states that we can use shorthand argument name. The shorthand I presume includes above. Yes it seems to! So $0 is the first argument - a bit like the index in array.
It is quite the change from the original closure to this. Return is implicit. Local constant not needed.
If we had two arguments, then it would be $0 and $1 etc.
Rule Number 5 - trailing closures
If the closure expression is the LAST argument, then you can move it outside the parentheses and write it as a trailing closure instead.
So a trailing closure is outside the parentheses and after the closure...
numArray.map() {$0 * 3}
So in this case, not much advantage. We can treat it like a normal function and put all the logic within.
Rule Number 6 - Ignoring parentheses
If the closure expression is the ONLY argument, then you can get rid of the parentheses all together.
numArray.map {$0 * 3}
These rules are all in the Apple guidebook.
Before I go on to the next section, still on Closures, I will do some extra reading and practice!
let doubledValues = [1,2,3,4]
let doubler = doubledValues.map { $0 * 2 }
Easy! No problems at all. *5 minute pause
Extra Reading
OK, so I am using this website....
https://medium.com/@abhimuralidharan/functional-swift-all-about-closures-310bc8af31dd
So I've read the key points. Nothing new to be honest. But some more practice using one of his examples -
let sumOfClosure = ({ (value1: Int, value2: Int) -> Int in
return value1 + value2
})
sumOfClosure(4, 5)
I did that myself, using previous closures to help. Makes much more sense how to go about closures. Let's shorten this even more.
Now this does NOT work, and good as it shouldn't!
let shorthandClosureSumOf = ({ (value1, value2) in
value1 + value2
})
There is nothing to infer the type - nothing at all!
This does work still -
let shorthandClosureSumOf = {(value1: Int, value2: Int) in value1 + value2 }
OK, some useful stuff there! A key point is you cannot use the real shorthand, unless the value type have been implied. So the earlier example with the array and map were different to these.
Finish Time - 16:26 (total time 35 minutes with all the delays; total 1 hour 15 for this blog entry)
Comments
Post a Comment