温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

为什么函数是一等公民

发布时间:2021-10-19 17:02:08 来源:亿速云 阅读:196 作者:iii 栏目:编程语言

这篇文章主要讲解了“为什么函数是一等公民”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“为什么函数是一等公民”吧!

关于一等公民[1](First-class citizen)看看维基百科的定义:

In programming language design, a first-class citizen (also type, object,  entity, or value) in a given programming language is an entity which supports  all the operations generally available to other entities. These operations  typically include being passed as an argument, returned from a function,  modified, and assigned to a variable.

大意是说,在编程语言中,所谓一等公民,是指支持所有操作的实体, 这些操作通常包括作为参数传递,从函数返回,修改并分配给变量等。

比如 int 类型,它支持作为参数传递,可以从函数返回,也可以赋值给变量,因此它是一等公民。

类似的,函数是一等公民,意味着可以把函数赋值给变量或存储在数据结构中,也可以把函数作为其它函数的参数或者返回值。关于函数是一等公民,在维基百科也有定义[2]。

In computer science, a programming language is said to have first-class  functions if it treats functions as first-class citizens. This means the  language supports passing functions as arguments to other functions, returning  them as the values from other functions, and assigning them to variables or  storing them in data structures. Some programming language theorists require  support for anonymous functions (function literals) as well.In languages with  first-class functions, the names of functions do not have any special status;  they are treated like ordinary variables with a function type. The term was  coined by Christopher Strachey in the context of "functions as first-class  citizens" in the mid-1960s.

函数作为一等公民的概念是 1960 年由英国计算机学家 Christopher Strachey[3]  提出来的。然而,并非所有语言都将函数作为一等公民,特别是早期,比如 C 语言中函数就不是一等公民,一些功能通过函数指针来实现的;再比如 C++、Java  等,都是后来的版本才加上的。

一般来说,函数式编程语言、动态语言和现代的编程语言,函数都会作为一等公民,比如:Scala、Julia 等函数式语言,JavaScript、Python  等动态语言,Go、Rust、Swift 等现代的编译型语言。

为了让大家对函数是一等公民有更深的理解,针对上文提到的一等公民的一等功能,我们看看 Go 语言是如何支持的。

匿名函数

函数一般是有名字的,但有时候没有名字的函数更简洁、好用。没有名字的函数叫匿名函数。

以下是 Go 语言匿名函数的一个例子:

package main  import (  "fmt" )  func main() {  fn := func() {   fmt.Println("This is anonymous function!")  }  fn()   fmt.Printf("The type of fn: %T\n", fn) }  // output: // This is anonymous function! // The type of fn: func()

在线运行:https://play.studygolang.com/p/IcInzZsAr0a。

在 Go 中,匿名函数最常使用的场景是开启一个 goroutine,经常会见到类似这样的代码:

go func() {   // xxxx }()

这里匿名函数定义后立即调用。此外,defer 语句中也常见。

定义函数类型

定义函数类型和其他类型类似,同时后半部分和匿名函数类似,只不过没有函数实现。比如 net/http 包中的 HandlerFunc  函数类型:

type HandlerFunc func(ResponseWriter, *Request)

怎么使用这个类型?能看懂这样的代码,表示你理解了:

var h http.HandlerFunc = func(w ResponseWriter, req *Request) {   fmt.Fprintln(w, "Hello World!") }

函数作为参数

意思是说,一个函数作为另一个函数的参数,也就是回调,在 JS 中很常见。在 Go 语言中也经常出现。文章开头的问题就是函数作为参数。根据  Gin 的 API 定义,router.GET 方法的签名如下:

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes

其中 HandlerFunc 是一个函数类型,它的定义如下:

type HandlerFunc func(*Context)

所以,router.GET("/users", Users) 中,Users 只是 GET 函数的参数,参数类型是 HandlerFunc,而 Users  的定义只要符合 HandlerFunc 即可:

func Users(ctx *gin.Context) {}

因为这里将函数 Users 作为参数,所以自然不需要给 Users 传递参数,Uers 的调用有 GET 内部负责,即所谓的回调。

函数作为返回值

函数作为返回值,在 Go 中,这样的函数一定是匿名函数。在进行 Web 开发时,中间件就会使用上函数作为返回值,还是以 Gin  为例,定义一个 Logger 中间件:

func Logger() gin.HandlerFunc {  return func(c *gin.Context) {   t := time.Now()    // Set example variable   c.Set("example", "12345")    // before request    c.Next()    // after request   latency := time.Since(t)   log.Print(latency)    // access the status we are sending   status := c.Writer.Status()   log.Println(status)  } }

从上文知道,gin.HandlerFunc 是一个函数类型,因此需要返回一个该类型的实例,而匿名函数(函数字面值)只要和 gin.HandlerFunc  类型的底层类型一致,会进行隐式转换,所以可以直接返回 func(c *gin.Context) {} 这个匿名类型。

经常听到高阶函数,函数是一等公民,就支持高阶函数。一个函数只要接收一个或多个函数类型参数;亦或是返回一个函数,这样的函数就叫做高阶函数。

闭包

闭包(Closure)是匿名函数的一个特例。当一个匿名函数所访问的变量定义在函数体的外部时,就称这样的匿名函数为闭包。

一个简单的例子:

package main  import (       "fmt" )  func main() {       a := 5     func() {         fmt.Println("a =", a)     }() }

在上面的程序中,匿名函数在第 10 行访问了变量 a,而 a 存在于函数体的外部。因此这个匿名函数就是闭包。

感谢各位的阅读,以上就是“为什么函数是一等公民”的内容了,经过本文的学习后,相信大家对为什么函数是一等公民这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI