Golang函数和函数变量的语义

huangapple go评论71阅读模式
英文:

Golang function and function variable semantics

问题

为什么我不能将递归函数定义为变量?我似乎可以定义任意函数,除了递归函数。

这是合法的:

func f(i int) int {
    if i == 0 {
        return 1
    }
    return i * f(i-1)
}

func main() {
    fmt.Println(f(2))
}

这是不合法的:

var f func(int) int = func(i int) int {
    if i == 0 {
        return 1
    }
    return i * f(i-1)
}

func main() {
    fmt.Println(f(2))
}

这是合法的,我猜测这是因为在初始化之后可以找到 f:

func main() {
    var f *func(int) int
    t := func(i int) int {
        if i == 0 {
            return 1
        }
        return i * (*f)(i-1)
    }
    f = &t
    fmt.Println((*f)(2))
}

所以看起来函数和变量声明的函数类型是不同对待的,尽管从阅读文档来看,我不会期望是这样的。我是否错过了文档中详细说明这一点的部分?

我期望不合法的情况能够工作,因为在其他语言中是可以的。比如在 JavaScript 中:

(function () {
  var f = function (i) {
    if (i == 0) {
      return 1;
    }
    return i * f(i - 1);
  };

  console.log(f(2));
})();
英文:

Why can't I define a recursive function as a variable? I seem to be able to define arbitrary functions except when they recurse.

This is legal:

func f(i int) int {
	if i == 0 {
		return 1
	}
	return i * f(i-1)
}

func main() {
	fmt.Println(f(2))
}

This is illegal:

var f func(int) int = func(i int) int {
	if i == 0 {
		return 1
	}
	return i * f(i-1)
}

func main() {
	fmt.Println(f(2))
}

This is legal and I'm guessing it is just because you can figure out f after initialization:

func main() {
	var f *func(int) int;
	t := func(i int) int {
		if i == 0 {
			return 1
		}
		return i * (*f)(i-1)
	}
	f = &t
	fmt.Println((*f)(2))
}

So it looks like it comes down to function and variable declarations of a function type are treated differently though from the reading the documentation I wouldn't expect that to be the case. Did I miss the part of the documentation detailing this?

I would expect the illegal case to work just because it works in other languages. Like in JavaScript:

(function () {
  var f = function (i) {
    if (i == 0) {
      return 1;
    }
    return i * f(i - 1);
  };

  console.log(f(2));
})();

答案1

得分: 49

以下代码是描述你所描述的做法的首选方式。请注意,你不需要创建额外的变量,也不需要一个指向函数的指针:

package main

import "fmt"

func main() {
    var f func(int) int
    f = func(i int) int {
        if i == 0 {
            return 1
        }
        return i * f(i-1)
    }
    fmt.Println(f(2))
}

这段代码定义了一个函数变量 f,并将其初始化为一个匿名函数。匿名函数内部使用递归的方式计算阶乘。最后,通过调用 f(2) 来输出结果。

英文:

The below code would be the preferred way of doing what you describe. Note that you do not have to create an additional variable, nor do you have a pointer to a function:

package main

import "fmt"

func main() {
    var f func(int) int
    f = func(i int) int {
        if i == 0 {
            return 1
        }
        return i * f(i-1)
    }
    fmt.Println(f(2))
}

huangapple
  • 本文由 发表于 2015年2月18日 06:27:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/28572349.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定