「Mac玩转仓颉内测版51」基础篇13 - 高阶函数与闭包

本篇详细介绍高阶函数闭包,这是仓颉语言中实现灵活逻辑的关键工具。高阶函数可将函数作为参数或返回值使用,而闭包能捕获其定义域中的变量,并在后续调用中保持状态。这些概念能让代码更加简洁、灵活,并提升复用性。


关键词
  • 高阶函数
  • 闭包
  • 函数作为参数和返回值
  • 捕获变量

一、高阶函数

高阶函数可以接受函数作为参数或将函数作为返回值,在回调、事件处理和逻辑组合中广泛使用。


1.1 函数作为参数
cangjie 复制代码
// 定义程序包名称为 cjcDemo
package cjcDemo

// 高阶函数 applyTwice:接收函数 fn 和整数 x,将 fn 应用两次并返回结果
func applyTwice(fn: (Int64) -> Int64, x: Int64): Int64 {
    return fn(fn(x))  // 两次应用 fn
}

// 定义增量函数 increment,将输入整数加 1
func increment(n: Int64): Int64 {
    return n + 1
}

// 主函数入口
main(): Int64 {
    let result = applyTwice(increment, 5)  // 结果为 7(5 + 1 + 1)
    println("结果: ${result}")  // 输出: 7
    return 0
}

applyTwice 展示了如何将函数作为参数传递,并多次调用其逻辑。


1.2 函数作为返回值
cangjie 复制代码
// 定义程序包名称为 cjcDemo
package cjcDemo

// 定义工厂函数 makeAdder,返回一个闭包函数
func makeAdder(increment: Int64): (Int64) -> Int64 {
    return { x: Int64 => x + increment }  // 返回匿名函数
}

// 主函数入口
main(): Int64 {
    let addFive = makeAdder(5)  // 创建加 5 的闭包
    let result = addFive(10)  // 结果为 15(10 + 5)
    println("结果: ${result}")  // 输出: 15
    return 0
}

这里展示了如何通过高阶函数返回一个匿名函数(闭包)。


二、闭包

闭包是函数或 lambda,从其定义域中捕获变量并保持状态,即使脱离了作用域,变量依然可用。


2.1 捕获变量的闭包示例
cangjie 复制代码
// 定义程序包名称为 cjcDemo
package cjcDemo

// 创建计数器函数,直接调用闭包以捕获可变变量
func createCounter() {
    var count = 0  // 初始化可变变量 count

    // 定义一个内部闭包函数,用于递增 count
    func increment() {
        count += 1  // 每次调用递增 count
        println("当前计数: ${count}")  // 打印当前 count 值
    }

    // 在函数内直接调用闭包,而不是将其返回
    increment()  // 第一次调用,输出: 当前计数: 1
    increment()  // 第二次调用,输出: 当前计数: 2
    increment()  // 第三次调用,输出: 当前计数: 3
}

// 主函数,程序入口
main(): Int64 {
    // 调用 createCounter 函数,执行闭包内部逻辑
    createCounter()

    return 0  // 返回 0 表示程序成功执行
}

此示例展示了闭包如何捕获变量,并在多次调用之间保留状态。


2.2 闭包的限制与错误处理
  1. 捕获的变量必须已初始化
cangjie 复制代码
func faultyClosure() {
    var x: Int64
    let closure = func() { println(x) }  // 错误:x 未初始化
    x = 10
    closure()
}
  1. 可变变量的捕获:捕获可变变量时,需注意避免逃逸问题,否则闭包只能在作用域内使用。

三、闭包的实际应用
  1. 回调函数与事件处理:闭包可用于处理异步事件中的状态。
  2. 计数器与缓存:闭包能在多次调用之间保存状态。
  3. 函数组合:通过高阶函数与闭包实现复杂逻辑。

四、闭包的高级概念
  1. 变量捕获的形式

    • 函数参数的默认值可以捕获外部变量。
    • 函数或 lambda可以引用定义域之外的局部变量。
    • 实例成员变量可以通过非成员函数访问。
  2. 非捕获的情况

    • 在闭包内引用的局部变量
    • 形参变量全局变量的访问。
  3. 传递性捕获:如果一个函数调用了捕获可变变量的闭包,该函数也会间接捕获这些变量。


小结

高阶函数与闭包是仓颉语言中重要的工具。高阶函数提高了代码的复用性,而闭包让状态在多次调用之间得以保持。理解它们的特性与限制,能让你编写更简洁、灵活的代码。


下篇预告

下一篇将介绍递归函数与尾递归优化,探讨如何在仓颉语言中实现高效递归调用。


上一篇: 「Mac玩转仓颉内测版50」小学奥数篇13 - 动态规划入门
下一篇: [「Mac玩转仓颉内测版52」基础篇14 - 递归函数与尾递归优化](#下一篇: 「Mac玩转仓颉内测版52」基础篇14 - 递归函数与尾递归优化)

作者:SoraLuna

链接:https://www.nutpi.net/thread?topicId=417

來源:坚果派

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


相关推荐
明月(Alioo)5 分钟前
机器学习入门,用Lima在macOS免费搭建Docker环境,彻底解决镜像与收费难题!
macos·docker·容器
小江村儿的文杰7 分钟前
UE4 Mac构建编译报错 no template named “is_void_v” in namespace “std”
macos·ue4
Sammyyyyy13 分钟前
Node.js 做 Web 后端优势为什么这么大?
开发语言·前端·javascript·后端·node.js·servbay
SuperHeroWu720 分钟前
【HarmonyOS 6】仿AI唤起屏幕边缘流光特效
华为·harmonyos·特效·鸿蒙6.0·流光·ai唤起·屏幕边缘
27^×41 分钟前
Java 内存模型与垃圾回收机制详解
java·开发语言
max5006001 小时前
本地部署开源数据生成器项目实战指南
开发语言·人工智能·python·深度学习·算法·开源
q567315231 小时前
手把手教你用Go打造带可视化的网络爬虫
开发语言·爬虫·信息可视化·golang
Bling_Bling_11 小时前
面试常考:js中 Map和 Object 的区别
开发语言·前端·javascript
MonkeyKing_sunyuhua1 小时前
mac怎么安装uv工具
python·macos·uv
程序喵大人2 小时前
写C++十年,我现在怎么设计类和模块?(附真实项目结构)
开发语言·c++·类和模板