Here we are on day 7. Today, I started learning about closures!
:idseparator: -
:idprefix:
:experimental:
:source-highlighter: rouge
:rouge-style: pastie
:imagesdir: /images
:source-linenums-option: on
:tip-caption: đź’ˇ
Today was, admittedly, a tough one.
Closures.
What can I say about them.
In some ways, a lot of ways, they make a lot of sense.
However, in others, they feel a little like voodoo.
If you’re not sure what I mean, take https://zetcode.com/golang/closure/[this quote] from zetcode.com:
A Go closure is an anonymous nested function which retains bindings to variables defined outside the body of the closure. Closures can hold a unique state of their own. The state then becomes isolated as we create new instances of the function.
This quote requires further context, also from zetcode:
A nested function, also called an inner function, is a function defined inside another function. An anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions
So, if I understand it all correctly, a Go Closure is an anonymous function that has knowledge of the state outside it’s own definition, even after that outside context is destroyed.
If so, I’m totally fine with needing some time to let this sink in, as I mull it over repeatedly.
In some ways, it seems to run totally counter to what I’m used to.
However, I also appreciate the benefits of a closure’s functionality.
I’m just struggling a little with them because the concept is still pretty new to me.
For complete transparency, I have worked with anonymous functions and closures in PHP, but not as much as I’d like to have.
Now, for a code example (of course!).
The below code is my first attempt at solving https://go.dev/tour/moretypes/26[the Fibonacci closure exercise] in the Go Tour, heavily inspired by other solutions.
[source,go]
package main
import “fmt”
func fibonacci() func() int {
first, second := 0, 1
return func() int {
output := first + second
first = second
second = output
return output
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
If you run it, you’ll see the following output:
1
2
3
5
8
13
21
34
55
89
Technically, I believe this solution is wrong, or at the least, incomplete, because afaik https://en.wikipedia.org/wiki/Fibonacci_number[a Fibonacci number] should start with the first number (0) not the second (1).
That said, in working through the solution, and just staring at it for what feels like the longest time, I do have a better appreciation of closures.
As the call to fibonacci()
returns the closure, which in turn has reference to two variables, first
and second
, in the outer scope of the closure, then after the call to fibonacci()
ends and its state is cleared up, the closure still has awareness of that state.
Given that, when it’s passed to fmt.Println()
in the for loop, then it can work with that acquired state.
Despite that, it still feels a little like magic.
Not to worry, though.
With time and more practice, I’m sure it will continue to sink in, and I’ll grow in my appreciation of closures.
Now; to use them more in PHP.
See you, link:/learning-golang/day8[next time]!
Join the discussion
comments powered by Disqus