【学习】重学Swift5-函数和闭包
五、函数和闭包
函数
常见形式
// 无形式参数的函数
func sayHelloWorld() -> String {
return "hello world"
}
print(sayHelloWorld()) // 多形式参数的函数
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
greet(person: "tim", alreadyGreeted: true) // 无返回值的函数
func greet(person: String) {
print("hello, \(person)!")
} // 多返回值的函数
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0] for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
} return (currentMin, currentMax)
} // 可选元组返回类型
func minMax(array: [Int]) -> (min: Int, max: Int)? { if array.isEmpty {return nil} var currentMin = array[0]
var currentMax = array[0] for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
} return (currentMin, currentMax)
} // 隐式返回的函数
// 如果整个函数体是一个单一表达式,那么函数可以隐式返回这个表达式
func greeting(person: String) -> String {
"hello " + person + "!"
}
print(greeting(person: "Tom"))
实参标签、形参名和返回值
/* 每一个函数的形式参数都包含实际参数标签和形式参数名。实际参数标签用在调用函数的时候;在调用函数的时候每一个实际参数前面都要写实际参数标签。形式参数名用在函数的实现当中。默认情况下,形式参数使用它们的形式参数名作为实际参数标签。
所有的形式参数必须有唯一的名字。尽管有可能多个形式参数拥有相同的实际参数标签,唯一的实际参数标签有助于让你的代码更加易读
*/
func someFunction(firstParameterName: Int, secondParameterName: Int) { }
someFunction(firstParameterName: 1, secondParameterName: 3)
上面的中没有定义实际参数标签,所以使用形式参数(firstParameterName、secondParameterName)名作为实参标签。在函数体内部使用形参实现逻辑。 // 指定实际参数标签
/*
在提供形式参数名之前写实际参数标签,用逗号分隔
如果你为一个形式参数提供了实际参数标签,那么这个实际参数就必须在调用函数的时候使用标签
实际参数标签的使用能够让函数的调用更加明确,更像是自然语句,同时还能提供更可读的函数体并更清晰的表达你的意图
*/
func greet(person: String, frome hometown: String) -> String {
return "hello \(person)! Glad you coule visit frome \(hometown)"
}
print(greet(person: "Bill", frome: "Cupertino"))
上面的中第一个参数没有定义实际参数标签,所以使用形式参数(person)名作为实参标签。第二个参数指定了(from)作为实际参数标签,(hometown)作为形式参数名。所以在调用的时候显示了(from),在内部使用(hometown) // 省略实际参数标签 使用_替代
func someFunction(_ firstParameterName: Int, secondParameterName: Int) { }
someFunction(1, secondParameterName: 3)
上面的中第一个使用_来省略实际参数标签 // 默认形式参数值
func someFunction(parameterWithDefault: Int = 12) {
print(parameterWithDefault)
}
someFunction(parameterWithDefault: 44)
someFunction() // 可变形式参数
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for num in numbers {
total += num
}
return total
}
arithmeticMean(1, 2, 3)
arithmeticMean(1) // 输入输出形式参数
/*
可变形式参数只能在函数的内部做改变。如果想函数能够修改一个形式参数的值,而且你想这些改变在函数结束后依然生效,就需要将形式参数定义为输入输出形式参数。
在形式参数定义开始的时候在前面添加一个inout关键字可以定义一个输入输出形式参数。
只能把变量作为输入输出形式参数的实际参数,再将变量作为实际参数传递给输入输出形式参数的时候,直接在它的前面添加一个&来明确可以被函数修改
输入输出形式参数不能有默认值,可变形式参数不能标记为inout
*/
func swapTwoInts(_ a:inout Int, _ b:inout Int) {
let temp = a
a = b
b = temp
} var a = 3
var b = 4;
swapTwoInts(&a, &b)
print(a, b)
函数类型和内嵌函数
// 函数类型由形式参数类型,返回类型组成
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func muliplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
上面两个都是(Int, Int) -> Int 类型 // 使用函数类型
var mathFunction: (Int, Int) -> Int = addTwoInts(_:_:)
print(mathFunction(2, 4))
// 作为参数
func printMathResult(_ mathFunction:(Int, Int) -> Int, _ a: Int, _ b: Int) {
print("result:\(mathFunction(a,b))")
}
printMathResult(addTwoInts(_:_:), 3, 4)
// 作为返回值
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward(_:) : stepForward(_:)
} // 内嵌函数
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(_ input: Int) -> Int { return input + 1 }
func stepBackward(_ input: Int) -> Int {
return input - 1
}
return backwards ? stepBackward(_:) : stepForward(_:)
}
闭包
定义
/*
闭包是可以在你的代码中被传递和引用的功能性独立代码块
闭包能够捕获和存储定义在其上下文中的任何常量和变量的引用。
*/ /*
闭包符合如下三种形式中的一种:
1.全局函数是一个有名字但不会捕获任何值的闭包;
2.内嵌函数是一个有名字且能从其上层函数捕获值的闭包;
3.闭包表达式是一个轻量级语法所写的可以捕获其上下文中常量或变量值的没有名字的闭包
*/ // 闭包表达式是一种在简短行内就能写完闭包的语法。
// 闭包表达式语法能够使用常量形式参数、变量形式参数和输入输出形式参数,但不能提供默认值。可变形式参数也能使用,但是需要在形式参数列表的最后使用,元组也可被用来作为形式参数和返回类型
// 结构如下
{ (parameters) -> (return type) in
statements
} // 不使用闭包
let names = ["zhangsan", "lisi", "wangwu", "maliu"]
let fNames = names.sorted() func backward(s1: String, s2: String) -> Bool {
return s1 > s2
}
let sNames = names.sorted(by: backward(s1:s2:)) // 使用闭包
let sNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
}) let sName = names.sorted(by:{ s1, s2 in return s1 > s2 } ) // 单表达式闭包能通过从它们的声明中删除return关键字来隐式返回单个表达式的结果
let sName = names.sorted(by:{ s1, s2 in s1 > s2 } ) // swift自动对行内闭包提供间歇实际参数名,可以通过$0,$1,$2等名字来引用闭包的实际参数值
let sName = names.sorted(by:{ $0 > $1 } ) // 运算符函数
/*
swift的String类型定义了关于大于号(>)的特定字符串实现,其类型正好与sorted(by:)所需形参一致,所以可以更简单的书写
*/
let sName = names.sorted(by: > ) // 尾随闭包
/*
尾随闭包是一个被书写在函数形式参数的括号外面(后面)的闭包表达式
条件:只有一个参数,且是一个闭包,可以直接加闭包,并且去掉括号
*/
let sName = names.sorted{$0 > $1 }
闭包捕获值
/*
一个闭包能够从上下文捕获已被定义的常量和变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍能够在其函数体内引用和修改这些值。 在swift中,函数和闭包都是引用类型。 如果你分配了一个闭包给类实例的属性,并且闭包通过引用该实例或者它的成员来捕获实例,你将在闭包和实例间会产生循环引用
*/
逃逸闭包、自动闭包
// 逃逸闭包
// 自动闭包
【学习】重学Swift5-函数和闭包的更多相关文章
- iOS学习笔记42-Swift(二)函数和闭包
上一节我们讲了Swift的基础部分,例如数据类型.运算符和控制流等,现在我们来看下Swift的函数和闭包 一.Swift函数 函数是一个完成独立任务的代码块,Swift中的函数不仅可以像C语言中的函数 ...
- CC2530红外学习球学码函数(P1.2接红外一体接收头,使用定时器tim1的复用功能2)
P1.2GPIO配置: void cap_gpio_init(){ P1SEL |= 0x04; P1DIR &= ~0x04; PERCFG |= 0x40; P2SEL |= 0x20; ...
- scala学习笔记4:函数和闭包
以下主要记录的是看完scala in programming这本书functions and closures(第八章)后的要点总结. 1,函数可以存在的地方:函数方法,嵌套函数. 2,关于funct ...
- javascript进阶课程--第三章--匿名函数和闭包
javascript进阶课程--第三章--匿名函数和闭包 一.总结 二.学习要点 掌握匿名函数和闭包的应用 三.匿名函数和闭包 匿名函数 没有函数名字的函数 单独的匿名函数是无法运行和调用的 可以把匿 ...
- 前端学习 第六弹: javascript中的函数与闭包
前端学习 第六弹: javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) { ...
- 记录我的 python 学习历程-Day13 匿名函数、内置函数 II、闭包
一.匿名函数 以后面试或者工作中经常用匿名函数 lambda,也叫一句话函数. 课上练习: # 正常函数: def func(a, b): return a + b print(func(4, 6)) ...
- 【Go语言学习】匿名函数与闭包
前言 入坑 Go 语言已经大半年了,却没有写过一篇像样的技术文章,每次写一半就搁笔,然后就烂尾了. 几经思考,痛定思痛,决定金盆洗手,重新做人,哦不,重新开始写技术博文. 这段时间在研究Go语言闭包的 ...
- JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)
1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. ...
- 《JS语言精粹》学习笔记 函数部分の闭包
要理解闭包,首先要理解变量作用域,变量的作用域就两种,全局变量和局部变量,函数内部可以直接读取全局变量,函数外部无法读取函数内部的局部变量. 闭包定义:能读取函数内部局部变量的函数就是闭包,而只有函数 ...
- swift 学习(二)基础知识 (函数,闭包,ARC,柯里化,反射)
函数 func x(a:Int, b:Int) {} func x(a:Int, b:Int) -> Void {} func x(a:Int, b:Int) ->(Int,Int ...
随机推荐
- C++ pair对组 学习总结
----------------------------------------------pair对组 对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型两个值可以分别用pair的 ...
- Linux百度网盘优化三板斧
解决Linux百度网盘CPU占用过高,下载进度卡住,频繁崩溃退出问题. 解决Linux百度网盘CPU占用过高问题 夏天到了,百度网盘下载时conky显示CPU温度飙升到99摄氏度,风扇嗷嗷叫,但CPU ...
- type和interface与namespace和module
type 和 interface 的区别 type 可以定义基本类型 也可以定义对象.数组.函数等 // 1. 定义基本类型 type StudentNameType = string; const ...
- 前端开发系列061-网络篇之HTML页面渲染的基本过程
本文描述了HTML页面渲染的基本(一般)过程,需要说明的是该文并不包含关于HTML解释器.CSS解释器.JavaScript引擎等相关部分内部的具体处理细节.该文旨在简单介绍网页从加载到被我们看到过程 ...
- Codeforces Round #693 (Div. 3) ABCDE题解
A. Cards for Friends 思路:折纸游戏,看长宽能各折多少次,就是2的几次方,相乘即可. view code #include<iostream> #include< ...
- SciTech-Mathmatics - Advanced Linear Algebra(高等线性代数): Vector、Vectors、Vector Space 和 Matrix 的奇妙联系
SciTech-Mathmatics - Advanced Linear Algebra(高等线性代数): Vector.Vectors.Vector Space和 Matrix 的奇妙联系 \(\l ...
- SciTech-Mathmatics-Real Space + Taylor Equation + Exponential Functions+Trigonometrical Functions + Complex Space + Euler's Equation
Derivative and Slope Quick review: a \(derivative\) gives us the \(\text{slope of a function}\) at \ ...
- redis过期机制及注意事项
按Redis官网说法:对于设置了过期时间的key,有2种清理机制,原文如下: How Redis expires keys Redis keys are expired in two ways: a ...
- Windows11升级更新后桌面黑屏的问题
近来有电脑基地的用户反馈更新升级Windows11系统后进入电脑桌面就黑屏,但是又有鼠标和语言栏,也可以打开任务管理器.虽然,可以使用运行explorer.exe想要重启桌面,但是没有任何效果,这该怎 ...
- fantasy-talking:实现图片加音频生成对嘴数字人
引言:一张图也能"说话"? 你有没有想过,一张静态的照片,配上一段音频,就能变成一段"对嘴"的视频?不是简单的口型同步,而是让图片中的人物"活过来&q ...