24 闭包和闭包表达式

简介: 闭包和闭包表达式

闭包和闭包表达式

闭包的概念

  • 闭包是可以在你的代码中被传递和引用的功能性独立代码块
  • 闭包能够捕获和存储定义在其上下文中的任何常量和变量的引用,这也就是所谓的闭包并包裹那些常量和变量,因为被称为“闭包”,Swift能够为你处理所有关于捕获的内存管理的操作
  • 在函数章节中有介绍的全局和内嵌函数,实际上是特殊的闭包。闭包符合如下三种形式中的一种:
  1. 全局函数是一个有名字但不会捕获任何值的闭包
  2. 内嵌函数是一个有名字且能从其上层函数捕获值得闭包
  3. 闭包表达式是一个轻量级语法所写的可以捕获其上下文中常量或变量值得没有名字的闭包


闭包表达式

  • 闭包表达式是一种在简短行内就能写完闭包的语法


闭包表达式-从sorted函数说起

  • Swift的标准库提供了一个叫做sorted(by:)的方法,会根据你提供的排序闭包将已知类型的数组的值进行排序。一旦它排序完成,sorted(by:)方法会返回与原数组类型大小完全相同的一个新数组,该数组的元素是已排序好的。原始数组不会被sorted(by:)方法修改


image.png

闭包表达式语法

  • 闭包表达式语法能够使用常量形式参数、变量形式参数和输入输出形式参数,但不能提供默认值。可变形式参数也能使用,但需要在形式参数列表的最后面使用。元组也可被用来作为形式参数和返回类型


image.png

闭包表达式语法版本的backward

  • 将之前backward(_:_:)函数改为闭包表达式版本


image.png

从语境中推断类型

  • 因排序闭包为实际参数来传递给函数,故Swift能推断它的形式参数类型和返回类型
  • sorted(by:)方法期望它的形式参数是一个(String, String) -> Bool类型的函数。这意味着(String, String)和Bool类型不需要被写成闭包表达式定义中的一部分,因为所有类型都能被推断,返回箭头(->)和围绕在形式参数名周围的括号也能被省略


image.png

从单表达式闭包隐式返回

  • 单表达式闭包能够通过从它们的声明中删掉return关键字来隐式返回它们单个表达式的结果


image.png

简写实际参数名

  • Swift自动对行内闭包提供简写实际参数名,可以通过0,1, $2等名字来引用闭包的实际参数值


image.png

运算符函数

  • Swift的String类型定义了关于大于号(>)的特定字符串实现,让其作为一个有两个String类型形式参数的函数并返回一个Bool类型的值。这正好与sorted(by:)方法的形式参数需要的函数相匹配。因为,你能简单地传递一个大于号,并且Swift将推断你想使用大于号特殊字符串函数实现


image.png

尾随闭包

  • 如果你需要将一个很长的闭包表达式作为函数最后一个实际参数传递给函数,使用尾随闭包将增强函数的可读性。尾随闭包是一个被书写在函数形式参数的括号外面(后面)的闭包表达式


image.png

闭包如何捕获值

捕获值

  • 一个闭包能够从上下文捕获已被定义的常量和变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍能够在其函数体内引用和修改这些值


image.png


  • 作为一种优化,如果一个值没有改变或者在闭包的外面,Swift可能会使用这个值得拷贝而不是捕获
  • Swift也处理了变量的内存管理操作,当变量不再需要时会被释放


image.png

  • 如果你建立了第二个incrementer,它将会有一个新的、独立runningTotal变量的引用


image.png

闭包是引用类型

  • 在Swift中,函数和闭包都是引用类型
  • 无论你什么时候赋值一个函数或者闭包给常量或者变量,你实际上都是将常量和变量设置为对函数和闭包的引用


image.png

  • 如果你分配了一个闭包给类实例的属性,并且闭包通过引用该实例或者它的成员来捕获实例,你将在闭包和实例间会产生循环引用


逃逸闭包和自动闭包


逃逸闭包

  • 当闭包作为一个实际参数传递给一个函数的时候,并且它会在函数返回之后调用,我们就说这个闭包逃逸了。当你声明一个接受闭包作为形式参数的函数时,你可以在形式参数前写@escaping来明确闭包是允许逃逸的
  • 闭包可以逃逸的一种方法是被储存在定义与函数外的变量里。比如说,很多函数接受闭包实际参数来作为启动异步任务的回调。函数在启动任务后返回,但是闭包要直到任务完成--闭包需要逃逸,以便于稍后调用


image.png


  • 让闭包@escaping意味着你必须在闭包中显式地引用self


image.png


自动闭包

  • 自动闭包是一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包。它不接收任何实际参数,并且当它被调用时,它会返回内部打包的表达式的值
  • 这个语法的好处在于通过写普通表达式代替显示闭包而使你省略包围函数形式参数的括号


image.png


自动闭包允许你延迟处理,因为闭包内部的代码直到你调用它的时候才会运行。对于有副作用或者占用资源的代码来说很有用,因为它可以允许你控制代码何时才进行求值


image.png


  • 当你传一个闭包作为实际参数到函数的时候,你会得到与延迟处理相同的行为

image.png


通过@autoclosure标志标记它的形式参数使用了自动闭包。现在你可以调用函数就像它接受了一个String实际参数而不是闭包。实际参数自动地转换为闭包,因为customerProvider形式参数的类型被标记为@autoclosure标记


image.png

自动+逃逸

  • 如果你想要自动闭包允许逃逸,就同时使用@autoclosure和@escaping标志


image.png








目录
相关文章
|
机器学习/深度学习 人工智能 搜索推荐
AIGC工具——文心一格
【1月更文挑战第12天】AIGC工具——文心一格
994 3
AIGC工具——文心一格
|
C++ 索引 容器
【C++STL基础入门】深入浅出string类insert和appand
【C++STL基础入门】深入浅出string类insert和appand
349 1
链接远程服务器出现 Connection closed by foreign host
链接远程服务器出现 Connection closed by foreign host
|
机器学习/深度学习 并行计算 异构计算
NVIDIA CUDA/cuDNN历代版本下载地址
NVIDIA CUDA/cuDNN历代版本下载地址
4872 0
NVIDIA CUDA/cuDNN历代版本下载地址
|
11月前
|
存储 安全 关系型数据库
2024 Mysql基础与进阶操作系列之MySQL触发器详解(21)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
MySQL触发器的使用场景之数据完整性约束、如何具体创建person的日志表、触发器与存储过程的对比与选择、触发器的性能和注意事项等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
存储 并行计算 测试技术
NumPy 性能优化:提升 Python 数值计算的速度
【8月更文第30天】Python 是一种广泛使用的编程语言,在科学计算领域尤其受欢迎。然而,由于 Python 的动态类型和解释执行机制,其在处理大规模数值数据时可能会显得相对较慢。为了克服这一限制,NumPy(Numerical Python)库提供了高性能的多维数组对象以及一系列用于操作这些数组的函数。本文将探讨如何利用 NumPy 来提高 Python 中数值运算的效率。
1180 1
|
数据处理 Python
【Python】已解决:raise XLRDError(FILE_FORMAT_DESCRIPTIONS[file_format]+‘; not supported’) xlrd.biffh.XLRD
【Python】已解决:raise XLRDError(FILE_FORMAT_DESCRIPTIONS[file_format]+‘; not supported’) xlrd.biffh.XLRD
397 1
|
人工智能 云计算
全球30m不透水地表动态数据集(GISD30)
全球30m不透水地表动态数据集(GISD30)
202 0
|
负载均衡 Java Nacos
restTemplate loadbalance 负载均衡使用demo 案例 原理以及全网最细源码解析
restTemplate loadbalance 负载均衡使用demo 案例 原理以及全网最细源码解析
restTemplate loadbalance 负载均衡使用demo 案例 原理以及全网最细源码解析