I am reading Closure example in Mark Summerfield's book Programming in Go Section 5.6.3. He defines Closure as a "function which "captures" any constants and variables that are present in the same scope where it is created, if it refers to them."
He says that one use of closure is anonymous functions (or function literals in Go)
He gives this examples:
addPng := func(name string) string { return name + ".png" }
addJpg := func(name string) string { return name + ".jpg" }
fmt.Println(addPng("filename"), addJpg("filename"))
I understand that anonymous function named addPng is a wrapper for the string concatenation operator +.
If I understand correctly, he is assigning an anonymous function a name then calling the function with that name. I don't see the point of this example. If I define the same function addPng and call it inside main() I get the same result:
package main
import ("fmt")
func addPng (name string) string {
return name + ".png"
}
func main() {
fmt.Println(addPng("filename"))
}
I understand that I cannot define and use a function inside another function. But why is the anonymous function in Summerfield's example called "Closure"? And why use a wrapper function? What am I missing?
Here's an example of using a closure for state representation.
package main
import "fmt"
func NextFibonacci() func() int {
a, b := 0, 1
return func() (f int) {
f, a, b = a, b, a+b
return
}
}
func main() {
nf := NextFibonacci()
f := make([]int, 7)
for i := range f {
f[i] = nf()
}
fmt.Println(len(f), f)
}
Output:
7 [0 1 1 2 3 5 8]
It's not for the first time I see someone referring to this particular book where the cited material is either plain wrong or basically missing the point completely.
Let me stop talking about the book here by suggesting to not use it at all.
For a good and correct definition of a closure, see Wikipedia. Pay attention to the adjective 'lexical'.
Related
I'm coming from an Scala background, and in Scala, you could define functions both as a single value, or an actual function, for instance:
val inc1: Int => Int = _ + 1 // single FUNCTION value
def inc2(x: Int): Int = x + 1 // normal function definition
// in this case "inc1 eq inc1" is true, since this is a single instance
// but "inc2 eq inc2" is false
And these 2 have some differences (i.e., size allocation, first one is a single instance, while the other one returns an instance each time it is invoked, ...), so based on the use case, we could kind of reason which one to use. Now I'm new to golang, and wanted to know if the below 2 function definitions (correct me if I'm wrong with the phrase) differ in Golang, and if so, what are differences?
var inc1 = func(x int) int { return x + 1 }
func inc2(x int) int { return x + 1 }
Thanks in advance!
Scala borrows a lot from functional programming. Go does not.
(If you've used multiple other programming languages, you should definitely read the Go specification. It's not very long as Go is not a very large language, although the new generics definitely complicate things a bit.)
In Go, the func keyword introduces a function definition or function type, with the details being context-dependent. The var keyword introduces a variable declaration.1 So:
func inc2(x int) int { return x + 1 }
defines a function, inc2, whose code is as shown. But:
var inc1 = // ...
declares and then initializes a variable, inc1. The type and initial value of the variable are determined by the commented-out section, so:
var inc1 = func(x int) int { return x + 1 }
defines a function (with no name) whose code is as shown. That function is then assigned to the variable as its initial value, so that the implied type of the variable is func (int) int or function taking one argument of type int and returning one value of type int.
Having created a variable, you can now either call the function currently stored in that variable:
func callit(arg int) {
result := inc1(arg)
// ... do something with the result ...
}
Or you can assign a new value into the variable, e.g.:
func overwrite() {
inc1 = func(a int) int { return a * 2 } // name `inc1` is now misleading
}
Because inc2 is a function, you can't re-assign a new value to it: it's just a function, not a variable.
1Note that a variable declaration with an initialization can use the "short declaration" form:
func f() {
v := 3
// ...
}
where we leave out the type and just say "use the type of the expression to figure out the type of the declaration". This declares and initializes the variable. Short declarations can only appear in block scope, so these must be inside some function. Other than omitting the var keyword they do nothing that you couldn't do by including the var keyword, or sometimes multiple var keywords:
result, err := doit()
might require:
var result someType
var err error
result, err = doit()
when written without using the short-declaration form.
When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?
In my example, generate and generate2 both give me same result, is there a reason I should choose any one of them?
The code picks key 1 to generate combinations with key 3,4,5,
then picks key 2 to generate combinations with key 3,4,5.
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
src := map[int][]string{
1: []string{"1", "11", "111"},
2: []string{"2", "22"},
3: []string{"3"},
4: []string{"4"},
5: []string{"5", "55"},
}
result2 := generate2(src)
fmt.Println(result2)
result := generate(src)
fmt.Println(result)
}
func generate(src map[int][]string) []string {
var combo []string
var add = func(f []string) {
for _, v := range f {
for _, p := range src[3] {
for _, q := range src[4] {
for _, r := range src[5] {
combo = append(combo, v+p+q+r)
}
}
}
}
}
add(src[1])
add(src[2])
return combo
}
func generate2(src map[int][]string) []string {
var combo []string
var add = func(f []string, combo []string, src map[int][]string) []string {
for _, v := range f {
for _, p := range src[3] {
for _, q := range src[4] {
for _, r := range src[5] {
combo = append(combo, v+p+q+r)
}
}
}
}
return combo
}
combo = add(src[1], combo, src)
combo = add(src[2], combo, src)
return combo
}
When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?
It depends on what you want to achieve.
What you call "a function inside a function" is actually called "a closure" (and some people call it "lambda").
Closures capture variables from the outer lexical scope, referenced in its body. In Go, this capturing is done "by reference" or "by name" which basically means each time a closure is called it will "see" current values of the variables it closes over, not the values these variables had at the time the closure was created—observe that the program:
package main
import (
"fmt"
)
func main() {
i := 42
fn := func() {
fmt.Println(i)
}
fn()
i = 12
fn()
}
would output
42
12
Conversely, when you pass values as arguments to calls to a closure, each call will see exactly the values passed to it.
I hope you now see that what strategy to pick largely depends on what you want.
Conceptually, you may think of a closure as being an instance of an ad-hoc anonymous struct data type, the fields of which are pointers to the variables the closure closes over, and each call to that closure being analogous to calling some (anonymous, sole) method provided by that type (actually, that's what the compiler usually does behind your back to implement a closure).
Such "method" may have arguments, and whether it should have them, and what should go to the type's fields and what should be that method's arguments can be judged using the usual approach you employ with regular types.
In this context, there is no functional difference between the two functions. As you noticed, local functions have access to local variables without explicitly passing them. In your example you might prefer to use generate1 for easier reading.
I tried to make my own code for learning how to return multiple values in main function:
package main
import "fmt"
func main() {
fmt.Println("Enter a integer:")
var I int
fmt.Scanf("%d", &I)
fmt.Println("Accepted:", I)
O := half(I)
fmt.Println("Returned:", O)
}
func half(N int) (int, bool) {
var NA int
NA = N / 2
if NA%2 == 0 {
fmt.Println("even")
return NA, true
} else {
fmt.Println("odd")
return NA, false
}
}
And given error: half.go|11| multiple-value half() in single-value context.
However another variant are working:
package main
import (
"fmt"
)
func half(number int) (int, bool) {
if x := int(number % 2); x == 0 {
return x, true
} else {
return x, false
}
}
func main() {
fmt.Println(half(1))
fmt.Println(half(2))
}
What am I doing wrong? How to overcome my error?
If a function has 2 return values, you have to "expect" both of them or none at all. More on this: Return map like 'ok' in Golang on normal functions
Your half() function has 2 return values, so when using a short variable declaration to store the returned values in variables, you have to provide 2 variables:
O, even := half(I)
fmt.Println("Returned:", O, even)
In the second case, you're not storing the returned values, you are passing them to fmt.Println() which has the signature:
func Println(a ...interface{}) (n int, err error)
fmt.Println() has a variadic parameter, so you can pass any number of arguments to it. What happens here is that all the multiple return values of half() are passed as the value of the variadic parameter of Println(). This is allowed and detailed in Spec: Calls:
As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.
Note that when doing so, you are not allowed to pass / provide extra parameters, so for example the following is also a compile-time error:
fmt.Println("Returned:", half(10))
// Error: multiple-value half() in single-value context
Check out these similar questions:
Go: multiple value in single-value context
Avoid nesting from conjunction with function that returns 2 values in go?
fmt.Println accepts any number of arguments, so is ok accepting the results of half.
In the first one, you need to provide places for both variables. Either:
i,b := half(2)
or
i, _ := half(2)
if you don't need the second return.
A simple example:
package main
import "fmt"
func hereTakeTwo() (x, y int) {
x = 0
y = 1
return
}
func gimmeOnePlease(x int){
fmt.Println(x)
}
func main() {
gimmeOnePlease(hereTakeTwo()) // fix me
}
Is it possible to pass only first returned value from hereTakeTwo() without using an explicit _ assignment? Example of what I would like to avoid:
func main() {
okJustOne, _ := hereTakeTwo()
gimmeOnePlease(okJustOne)
}
What I want is to make gimmeOnePlease function able to receive an undefined number of arguments but take only first one OR a way to call hereTakeTwo function and get only first returned value without the necessity to use _ assignments.
Or on a last resort (crazy idea) use some kind of adapter function, that takes N args and reurns only first one, and have something like:
func main() {
gimmeOnePlease(adapter(hereTakeTwo()))
}
Why? I'm just testing the boundaries of the language and learning how flexible it can be to some purposes.
No, you cannot do that apart from one special case described in the Spec:
As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value.
The best you can do besides the temporary variables (which are the best option) is this:
func first(a interface{}, _ ...interface{}) interface{} {
return a
}
func main() {
gimmeOnePlease(first(hereTakeTwo()).(int))
}
Playground: http://play.golang.org/p/VXv-tsYjXt
Variadic version: http://play.golang.org/p/ulpdp3Hppj
in go tutorial following code is often seen:
a := foo()
b, c := foo()
or actually what I see is:
m["Answer"] = 48
a := m["Answer"]
v, ok := m["Answer"]
how many foo() is defined?
Is it two, one with one return type, another with two return type?
Or just one foo() with two return type defined, and somehow magically when only need one return value (a := foo()), another return value is omitted?
I tried
package main
func main() {
a := foo()
a = 1
}
func foo() (x, y int) {
x = 1
y = 2
return
}
func foo() (y int) {
y = 2
return
}
But I got error message foo redeclared in this block
While some built in operations support both single and multiple return value modes (like reading from a map, type assertions, or using the range keyword in loops), this feature is not available to user defined functions.
If you want two versions of a function with different return values, you will need to give them different names.
The Effective Go tutorial has some good information on this.
Basically, a function defines how many values it returns with it's return statement, and it's function signature.
To ignore one or more of the returned values you should use the Blank Identifier, _(Underscore).
For example:
package main
import "fmt"
func singleReturn() string {
return "String returned"
}
func multiReturn() (string, int) {
return "String and integer returned", 1
}
func main() {
s := singleReturn()
fmt.Println(s)
s, i := multiReturn()
fmt.Println(s, i)
}
Playground
The v, ok := m["answer"] example you've given is an example of the "comma, ok" idiom (Also described in the Effective Go link above). The linked documentation uses type assertions as an example of it's use:
To extract the string we know is in the value, we could write:
str := value.(string)
But if it turns out that the value does not contain a string, the program will crash with a run-time error. To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string:
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q\n", str)
} else {
fmt.Printf("value is not a string\n")
}
If the type assertion fails, str will still exist and be of type string, but it will have the zero value, an empty string.