sfdcnoob
sfdcnoob

Reputation: 787

defining function inside of function

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
}

Upvotes: 1

Views: 2824

Answers (2)

kostix
kostix

Reputation: 55453

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.

Upvotes: 7

Wombologist
Wombologist

Reputation: 546

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.

Upvotes: 1

Related Questions