Swift的闭包(一):闭包简介、闭包表达式的优化
定义:Closures are self-contained blocks of functionality that can be passed around and used in your code.
跟oc中的block相似。
Capture can capture and store reference to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables.
闭包以下面三种形式中的一种存在:
- 全局函数是一个有名字并且不捕获任何变量的闭包;
- 嵌套函数(nested function)是有一个名字并且可以从他们的外层函数(enclosing function)捕获变量的闭包;
- 闭包表达式是没有名字,可以从他们的surrounding context中捕获变量;
Swift的闭包有干净、清晰的格式,并且有足够的优化,包括:
- 从上下文中推断参数和返回值;
- Implicit returns from single-expression closures;
- 简短的参数名字;
- 尾闭包语法
闭包表达式
闭包表达式提供几种语法优化,下面的例子展示通过迭代提炼一个单一的表达式sorted(by:),来展示这些优化。
排序方法
Swift的标准库提供一个叫做sorted(by:)的方法,基于用户提供的一个排序闭包的输出,可以对一个已知类型的数组进行排序。排序完成后,这个方法返回一个新的数组(跟原来的数组有相同的类型和元素数量)。
下面闭包表达式的例子,使用sorted(by:)方法对一组String值进行逆字母序排序。初始的数组如下:
var names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
sorted(by:)方法接受一个带两个相同类型的参数并返回一个Bool值的闭包。如果第一个值需要出现在第二个值后边,闭包需要返回true,否则,返回false。
这个例子是对一组String值进行排序,所以排序的闭包的需要是一个(String, String)->Bool类型的函数。
下面用一个正常的函数来作为这个排序闭包:
 func backward(_ s1: String, _ s2: String) -> Bool {
     return s1 > s2
 }
 var reversedNames = names.sorted(by: backward);
闭包表达式的语法

闭包表达式里的patameters可以是in-out参数,但不能有默认值。
下面这段代码展示闭包表示式的版本:
 reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
     return s1 > s2
 })
从上下文推断类型
因为上面例子中的闭包作为一个参数传递给了一个方法,Swift可以推断它参数的类型和返回值的类型。这个sorted(by:)方法是在一个String数组上调用,因此它的参数必须是一个(String, String) -> Bool类型的函数。这意味着(String, String)和Bool类型不需要写出来作为闭包定义的一部分。因为所有的类型都可以推断出来,返回的箭头->和参数两边的小括号也可以被删除:
 reversedNames = names.sorted(by: {s1, s2 in return s1 > s2})
从单表达式闭包隐式返回(Implicit Returns fro Single-Expression Closures)
单表达式闭包可以通过删除return关键字来隐式返回这个单表达式的结果:
reversedNames = names.sorted(by: {s1, s2 in s1 > s2})
简短的参数名字(Shorthand Argument Names)
Swift自动给内联闭包提供简短的参数名字,通过$0,$1,$2等来引用闭包的参数。
如果你在闭包雕大师中使用简短的参数名字,你可以从闭包的定义中删除闭包的参数列表,并且简短参数名字的数量和类型将通过预期的函数类型来推断。因为这个闭包表达式完全的组成了它的body,这个in关键字也可以删除。
 reversedNames = names.sorted(by: {$ > $})
运算符函数(Operator Functions)
实际上,对于上面的例子有一个更简短的写法。Swift的String类型实现了针对String类型的大于操作符作为一个有两个String类型参数和Bool返回值的函数。恰好跟sorted(by:)的需求吻合。因此,你可以简单的传递一个大于操作符,Swift将推断你想使用针对String的实现:
reversedNames = names.sorted(by: >)
尾闭包(Trailing Closures)
如果你需要给一个函数传递一个闭包作为函数的最后的参数,并且闭包表达式很长,写成尾闭包是更好的选择。一个尾闭包被写在函数调用小括号的后边。当你写尾闭包语法的时候,你不用为函数调用的闭包写参数标签。
 func someFunctionThatTasksAClosure(closure: () -> Void) {
 }
 //不使用尾闭包的函数调用
 someFunctionThatTasksAClosure(closure: {
     //closure's body
 })
 //使用尾闭包的函数调用
 someFunctionThatTasksAClosure() {
     //closure's body
 }
排序的例子使用尾闭包语法可以这么写:
let reversedNames = names.sorted() {
    (s1: String, s2: String) -> Bool in
    return s1 > s2
}
或者,这样:
 reversedNames = names.sorted() {$ > $}
如果闭包表达式是方法的唯一参数,并且你使用表达式作为尾闭包,那么在调用函数没有必要写小括号在函数名后边:
 reversedNames = names.sorted {$ > $}
参考:The Swift Programming Language(Swift 3)
Swift的闭包(一):闭包简介、闭包表达式的优化的更多相关文章
- Swift学习之十四:闭包(Closures)
		* 闭包(Closures) * 闭包是自包含的功能代码块,可以在代码中使用或者用来作为参数传值. * 在Swift中的闭包与C.OC中的blocks和其它编程语言(如Python)中的lambdas ... 
- Swift学习(三):闭包(Closures)
		定义 闭包(Closures)是独立的函数代码块,能在代码中传递及使用. 语法 {(parameters) -> return type in statements } 注:闭包表达式语法可以使 ... 
- Swift语法基础入门三(函数, 闭包)
		Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ... 
- Swift中文教程(四)--函数与闭包
		原文:Swift中文教程(四)--函数与闭包 Function 函数 Swift使用func关键字来声明变量,函数通过函数名加小括号内的参数列表来调用.使用->来区分参数名和返回值的类型: fu ... 
- 深入学习javaScript闭包(闭包的原理,闭包的作用,闭包与内存管理)
		前言 虽然JavaScript是一门完整的面向对象的编程语言,但这门语言同时也拥有许多函数式语言的特性. 函数式语言的鼻祖是LISP,JavaScript在设计之初参考了LISP两大方言之一的Sche ... 
- js闭包的作用域以及闭包案列的介绍:
		转载▼ 标签: it js闭包的作用域以及闭包案列的介绍: 首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ... 
- print(函数.__closure__) 来判断是不是闭包,  返回cell , 是闭包,       返回None 则不是闭包
		print(函数.__closure__) 来判断是不是闭包, 返回cell , 是闭包, None 则不是闭包 
- Swift高阶函数介绍(闭包、Map、Filter、Reduce)
		Swift语言有非常多函数式编程的特性.常见的map,reduce,filter都有,初看和python几乎相同,以下简介下 闭包介绍: 闭包是自包括的功能代码块,能够在代码中使用或者用来作为參数传值 ... 
- 初探swift语言的学习笔记三(闭包-匿名函数)
		作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29353019 转载请注明出处 假设认为文章对你有所帮助,请通过留言 ... 
随机推荐
- vsftpd.conf 联机手册
			vsftpd.conf - vsftpd 的配置文件 描述vsftpd.conf 可以用于控制 vsftpd, 以实现各种各样的功能. vsftpd 缺省到 /etc/vsftpd.conf 处查找此 ... 
- 解决win8与VC++6.0不兼容问题
			找到VC++6.0安装文件夹Bin下的MSDEV.EXE程序 将MSDEV名字改为MSDEV1(或MSDEV2,3...) 右击改好的MSDEV1,打开属性面板,选择兼容性,勾上“在兼容模式下运行”, ... 
- hadoop2.2.0 单机伪分布式(含64位hadoop编译) 及 eclipse hadoop开发环境搭建
			hadoop中文镜像地址:http://mirrors.hust.edu.cn/apache/hadoop/core/hadoop-2.2.0/ 第一步,下载 wget 'http://archive ... 
- BZOJ 1487 无归岛
			Description Neverland是个神奇的地方,它由一些岛屿环形排列组成,每个岛上都生活着之中与众不同的物种.但是这些物种都有一个共同的生活习性:对于同一个岛上的任意两个生物,他们有且仅有一 ... 
- Ferry Loading||
			uva10440:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&am ... 
- C++学习之容器的摸索
			初学容器,容易犯错的地方 1.vector,list和deque都是顺序容器.其中vector和deque都可以通过下标访问,而list不能 2. 容器的begin和end操作 c.begin()返回 ... 
- Linux企业级开发技术(2)——epoll企业级开发之epoll接口
			epoll的接口非常简单,总共只有三个函数: 1.int epoll_create(intsize); 生成一个 Epoll 专用的文件描述符,size用来告诉内核这个监听的数目一共有多大.这个参数不 ... 
- POJ 2289	Jamie's Contact Groups(多重匹配+二分)
			题意: Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是 ... 
- 【转】Chrome保存mhtml网页文件的方法 – 无需任何插件,完美!
			原文网址:http://www.ihacksoft.com/chrome-save-mht.html 在 Chrome 地址栏中键入“chrome://flags”,回车,这是一个 Chrome 的功 ... 
- 【模拟】Vijos P1005 超长数字串
			题目链接: https://vijos.org/p/1005 题目大意: 无限的正整数按顺序拼接成字符串S(S=12345678910111213...),给你一个字符串A(len<=200)求 ... 
