隐藏包级函数的递归函数

问题描述 投票:0回答:2

以下输出“2”。这是为什么?它不应该递归并打印“210”吗?

    package main

    var f = func(x int) {}

    func Bar() {
        f := func(x int) {
            if x >= 0 {
                println(x)
                f(x - 1)
            }
        }
        f(2)
    }

    func main() {
        Bar()
    }

go recursion scope
2个回答
2
投票

在全局范围内,

f
在这里定义为采用
int
并且不执行(和返回)任何操作。

    var f = func(x int) {}

当您在这里重新定义

f
时:

        f := func(x int) {
            if x >= 0 {
                println(x)
                f(x - 1)
            }
        }
在计算 func 之前,无法定义

f
,因此“新”
f
函数不在其自己的范围内。所以
f(x - 1)
仍然指的是全局函数。


0
投票

您的代码中有两个不同的变量,名为

f
,位于不同的范围中。第一:

    package main

    var f = func(x int) {}

这在包范围内声明并初始化了一个函数变量

f
。然后:

    func Bar() {
        f := func(x int) {
            if x >= 0 {
                println(x)
                f(x - 1)
            }
        }
        f(2)
    }

f 函数的范围内创建第二个 different_ 函数变量,

also
,称为
Bar()

第二个

f
变量在初始化之前并不存在。为了说明这一点,请考虑这个演示问题的简化示例:

package main

func main() {
   foo := foo + 1
   println(foo)
}

您希望这段代码做什么?输出

1
或编译失败?答案应该是显而易见的。

即使

foo
的词法声明出现在初始值表达式之前,当
评估
该表达式时,foo还不存在。

如果引入了名为

foo
的打包作用域变量,则现在可以使用引用该值的表达式来初始化
foo
中的
main

package main var foo = 2 func main() { foo := foo + 1 println(foo) }
现在可以正常编译并输出

3

foo
中的
main
据说是包范围中的
shadow
)。
我们可以通过将包作用域函数变量 
foo

重命名为其他内容(例如

f

)来说明代码中的相同问题。然后你应该发现你的代码不再编译:
pf

您可以在
这个游乐场
看到这一点。解决方案希望是显而易见的:更改分配给

package main var pf = func(x int) {} func Bar() { f := func(x int) { if x >= 0 { println(x) f(x - 1) // << compilation error: `f` does not exist } } f(2) } func main() { Bar() } 的函数的代码,使其引用 f

:
pf

那么很明显,
    package main

    var pf = func(x int) {}

    func Bar() {
        f := func(x int) {
            if x >= 0 {
                println(x)
                pf(x - 1)   // << compilation error: `f` does not exist
            }
        }
        f(2)
    }

    func main() {
        Bar()
    }
中的函数没有引用自身。

关键在于
f

中的函数没有名称

f不是
函数的名称,而只是变量的名称,该变量保存对匿名函数的引用
进一步思考,你会发现匿名函数是无法递归的。

© www.soinside.com 2019 - 2024. All rights reserved.