Swift-25-普通函数、闭包函数与Lamda表达式编程

2024-04-22 06:28

本文主要是介绍Swift-25-普通函数、闭包函数与Lamda表达式编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

函数

语法定义

先来看下swift中函数的定义,函数用关键字func来指定,语法相对复杂一点,主要有下列4种基本情况,还有比较复杂的,会在后续详细讲解。

无参函数定义

在这里插入图片描述

有参函数定义

在这里插入图片描述

一个简单的函数和函数调用示例如下:

    func printGreeting1() {print("Hello, playground.")}printGreeting1()func printGreeting2() ->String {return "Hello, playground.";}lef str = printGreeting2()

函数参数

函数有参数(parameter)之后就能做更多的事情了。利用参数可以向函数输入数据。我们之所以把函数的这部分称为“参数”,是因为它们可以根据调用者给函数传递的数据来改变自己的值。函数利用传递给自己的参数来执行任务或产生结果。 创建一个函数,利用参数打印更加个性化的问候信息,代码如下所示:

  //带一个参数func printPersonalGreeting(name: String) {print("Hello \(name), welcome to your playground.")}printPersonalGreeting(name: "Matt")

参数内部名称

语法格式为:paramName:ParamType,前面是参数名称,后面指参数类型。

      //带两个参数func divisionDescriptionFor(numerator: Double, denominator: Double) {print("\(numerator) divided by \(denominator) equals \(numerator / denominator)")}divisionDescriptionFor(numerator: 9.0, denominator: 3.0)

参数外部名称

语法格式为:outParName inParName:ParamType,依次表示外部调用时的参数名称,函数内部使用时的参数名称,参数类型。

这主要是为了代码的可读性更强而设计的,并没其它实际意义,但在调用时名称要匹配,如下例为外部调用重新声了一个名为to的参数名称以专让供外部调用使用。

func printPersonalGreeting(to name: String) { 13 print("Hello \(name), welcome to your playground.")
}
printPersonalGreeting(to: "Matt")

变长参数

语法格式为:paramName:ParamType... 注意最后面的三个点,就是变长参数的特殊关键字。

函数只能有一个变长参数,而且一般应该是函数参数列表中的最后一个。参数值在函数内是以数组的形式使用,比如下例所示:

func printPersonalGreetings(to names: String...) {for name in names {print("Hello \(name), welcome to the playground.")}
}
printPersonalGreetings(to: "Alex","Chris","Drew","Pat")

在这里插入图片描述

参数默认值

语法格式为:paramName:ParamType=value 用=号进行默认值赋值操作。

默认值应该放在函数参数数列表的末尾,如果形参有默认值,那么在调用函数时可以省略实参。

func divisionDescriptionFor(numerator: Double,denominator: Double, withPunctuation punctuation: String = ".") -> String { //默认值设置return "\(numerator) divided by \(denominator) equals \(numerator / denominator)\(punctuation)"
}//9.0 divided by 3.0 equals 3.0.  少传一个参数
print(divisionDescriptionFor(numerator: 9, denominator: 3))
//9.0 divided by 3.0 equals 3.0!  替换默认参数
print(divisionDescriptionFor(numerator: 9, denominator: 3, withPunctuation: "!"))

in-out 参数

语法格式为:paramName:input ParamType ,这里的input是一个关键字。

函数有时候需要修改实参的值。in-out(in-out parameter)能让函数影响函数体以外的变量。有两个注意事项:

  • 首先,in-out不能有默认值;
  • 其次,变长参数不能标记为inout;

in-out的作用其实就是用于实参值的修改,省去return的写法,也可认为是达到多返回的目的。

var error = "The request failed:"
//_是一个外部函数名,它有特殊含义,即如果定义外部参数名为_,则在函数被调用时可以不写参数名称
func appendErrorCode(_ code: Int, toErrorString errorString: inout String) {if code == 400 {errorString += " bad request."}
}//用inout修饰时,调用时需要加上&,表示函数会修改这个变量,此段代码运行最后error的值会被改写成The request failed: bad request. 这有点像return干的事。
appendErrorCode(400, toErrorString: &error)
error

函数返回值

函数结束执行后可以返回一些信息,这些信息称为函数的返回值,用return关键字来标识。

单个返回值

一个简单的例子,如下

func divisionDescriptionFor() -> String {return "numerator"
}var v = divisionDescriptionFor();

多个返回值

语法结构 : ->(name1:[DataType], name2:[DataType]),前面的name1和name2也可以省略,但不建议。

函数可以返回不止一个值。Swift用元组数据类型来做到这一点。

func sortEvenOddNumbers(_ numbers: [Int]) -> (evens: [Int], odds: [Int]) {var evens = [Int]()var odds = [Int]()for number in numbers {if number % 2 == 0 {evens.append(number)} else {odds.append(number)}}return (evens, odds)
}
let aBunchOfNumbers = [10,1,4,3,57,43,84,27,156,111]
let theSortedNumbers = sortEvenOddNumbers(aBunchOfNumbers)//The even numbers are: [10, 4, 84, 156]; the odd numbers are: [1, 3, 57, 43, 27, 111]
print("The even numbers are: \(theSortedNumbers.evens); the odd numbers are: \(theSortedNumbers.odds)")//一个更复杂的例子
func siftBeans(fromGroceryList list: [String]) -> (beanCount: Int, beansBought: [String]) 

多返回值运算

func +(lhs: Point, rhs: Point) -> Point {let newX = (lhs.x + rhs.x)let newY = (lhs.y + rhs.y)return Point(x: newX, y: newY)
}let p1 = Point(x: 1, y: 2)
let p2 = Point(x: 3, y: 5)let p3 = p1 + p2 //(4,7)
p3.x
p3.y

可空类型返回

某些情况下希望函数可返回一个可空实例(用?或!来标识的返回值),主要用于一个函数在某些情况下返回nil,在其它情况下返回一个有意义的实例值的场景

//此函数只有一个参数,参数为元组类型,其中元组的第二个值可有可无的
func grabMiddleName(fromFullName name: (String, String?, String)) -> String? {return name.1 //元组的索引,表示取参数中元组的第二个值,索引从0开始
}//因为函数调用时第二个元组值为nil,所以不会打印任何信息
let middleName = grabMiddleName(fromFullName: ("Matt",nil,"Mathias"))
if let theName = middleName {print(theName)
}

函数返回与中断

主要是用return语句,但这里用了一个特殊的语法guard,熟悉下其用法就可以了。

func greetByMiddleName(name: (first: String, middle: String?, last: String)) {//把middle的值绑定到middleName常量上guard let middleName = name.middle else {print("Hey there!")return}print("Hey \(middleName)!")
}greetByMiddleName(name: ("Matt","Danger","Mathias"))

嵌套函数

Swift的函数定义可以嵌套。嵌套函数在另一个函数定义的内部声明并实现。嵌套函数在包围它的函数以外不可用。当需要一个函数只在另一个函数内部做一些事情时,这个特性很有用。

func areaOfTriangleWith(base: Double, height: Double) -> Double {let numerator = base * height//嵌套函数func divide() -> Double {return numerator / 2}return divide()
}
areaOfTriangleWith(base: 3.0, height: 5.0) //~~ 7.5

声明函数型变量

主要是把函数定义为一个普通变量,这样就可以把函数做为参数传递了,比如下面代码的实现,就是为了把sortEvenOddNumbers做为参数传递。

func sortEvenOddNumbers(_ numbers: [Int]) -> (evens: [Int], odds: [Int]) {return (evens, odds)
}//创建了一个evenOddFunction常量,其值是sortedEvenOddNumbers(_:)函数
let evenOddFunctionType: ([Int]) -> ([Int], [Int]) = sortEvenOddNumbers

闭包

闭包是在应用中完成特定任务的互相分离的功能组,类似于函数但省去了命名和声明,相比函数而言会比较轻量化。先举一个子来一个直观的感受,下面是一个数组排序的例子:

let volunteerCounts = [1,3,40,32,2,53,77,13]func sortAscending(_ i: Int, _ j: Int) -> Bool {return i < j
}
//~~ [1, 2, 3, 13, 32, 40, 53, 77]
let volunteersSorted = volunteerCounts.sorted(by: sortAscending)

如果采用闭包,则代码可以更简单,如下所示:

let volunteerCounts = [1,3,40,32,2,53,77,13]
let volunteersSorted = volunteerCounts.sorted(by: {(i: Int, j: Int) -> Bool inreturn i < j
})

语法结构

基础语法如下例:

{ (parameters) -> return type in // 代码
}
  • 闭包整体代码写在 {} 中;
  • (parameters) 是参数部分;
  • -> return type 表示返回值
  • in 是一个关键字,用来分隔前两部分与代码的实现;

上面的例子还可以再简化:

//简化版本1
let volunteersSorted = volunteerCounts.sorted(by: { i, j in i < j })//简化版本2:$0代表第一个参数,$1代表第二个参数,依此类推,称为快捷语法参数
let volunteersSorted = volunteerCounts.sorted { $0 < $1 }

闭包的写法虽然可以简单再简单,但需要和可读性之间做下权衡,个人还是比较建议用第1种写法,这也是大多数语言的实现方式。

闭包做为函数返回值

一般应用于函数的返回值为另一个函数的场景。下面的makeTownGrand函数返回值为一个函数,注意第一个->后面的(Int, Int) -> Int 其实是一个闭包的写法。

func makeTownGrand() -> (Int, Int) -> Int {func buildRoads(byAddingLights lights: Int, toExistingLights existingLights: Int) -> Int {return lights + existingLights}return buildRoads
}
var stoplights = 4
//此处townPlanByAddingLightsToExistingLights是一个函数变量
let townPlanByAddingLightsToExistingLights = makeTownGrand()
stoplights = townPlanByAddingLightsToExistingLights(4, stoplights)
print("Town has \(stoplights) stop lights.") //Town has 8 stop lights.

闭包做为函数参数

一般应用于函数的参数为另一个函数的场景。下成示例中makeTownGrand函数的第二个参数为一个函数。

func makeTownGrand(withBudget budget: Int, condition: (Int) -> Bool) //第二个参数为一个函数-> ( (Int, Int) -> Int )? { //返回值为函数if condition(budget) {func buildRoads(byAddingLights lights: Int, toExistingLights existingLights: Int) -> Int {return lights + existingLights}return buildRoads} else {return nil}
}//本例子中做为函数参数传统
func evaluate(budget: Int) -> Bool {return budget > 10_000
}var stoplights = 4
//evaluate函数为第二个参数
if let townPlanByAddingLightsToExistingLights = makeTownGrand(withBudget: 1_000, condition: evaluate) {stoplights = townPlanByAddingLightsToExistingLights(4, stoplights)
}if let newTownPlanByAddingLightsToExistingLights = makeTownGrand(withBudget: 10_500, condition: evaluate) {stoplights = newTownPlanByAddingLightsToExistingLights(4, stoplights)
}//~~ Town has 8 stop lights.
print("Town has \(stoplights) stop lights.")

捕获闭包函数内部的变量

闭包和函数能记录在其闭合作用域中定义的变量所封装的内部信息。下面的makePopulationTracker函数的返回值为一函数类型。

func makePopulationTracker(forInitialPopulation population: Int) -> (Int) -> Int {var totalPopulation = populationfunc populationTracker(growth: Int) -> Int {totalPopulation += growthreturn totalPopulation}return populationTracker
}var currentPopulation = 5_422//growBy为一函数
let growBy = makePopulationTracker(forInitialPopulation: currentPopulation) //返回函数(Int) -> Int 
growBy(500) //5922
growBy(500) //6422
growBy(500) //6922
currentPopulation = growBy(500) //7422

再往下写点代码,前两行代码要说明的是闭包是引用类型,当把函数赋给一个常量或变量时,实际上是一个指针引用,并不是副本。但后面两行代码如果通过新的变量指向这个函数,则其作用域变会改变了。

let anotherGrowBy = growBy
anotherGrowBy(500) //7922var bigCityPopulation = 4_061_981
let bigCityGrowBy = makePopulationTracker(forInitialPopulation: bigCityPopulation) //7422bigCityPopulation = bigCityGrowBy(10_000) //4071981

lamda函数式编程

Swift的函数式编程和java差不太多。简单来讲lamda表达式,使代码更简洁,但也更难维护。闭包是实现函数编程的基础,因为函数式编程要求闭包函数可以和其它基本数据类型一样,可作为返回值从别的函数返回,也可以作为参数传递给别的函数,还可以存储在变量中。

map( _: )映射

遍历集合,实现原始数据的变换操作

let precinctPopulations = [1_244, 2_021, 2_157]
let projectedPopulations = precinctPopulations.map {(population: Int) -> Int inreturn population * 2
}
projectedPopulations //[2488, 4042, 4314]

filter( _: )筛选

遍历集合,实现原始数据的筛选

let precinctPopulations = [2488, 4042, 4314]
let bigProjections = projectedPopulations.filter {(projection: Int) -> Bool inreturn projection > 4_000
}
bigProjections //[4042, 4314]

reduce( _ : _ : )统计

遍历集合,实现原始数据的累加统计

let precinctPopulations = [2488, 4042, 4314]
let totalProjection = projectedPopulations.reduce(0) {(accumulatedProjection: Int, precinctProjection: Int) -> Int inreturn accumulatedProjection + precinctProjection
}
totalProjection //10844

这篇关于Swift-25-普通函数、闭包函数与Lamda表达式编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/925021

相关文章

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

python中update()函数的用法和一些例子

《python中update()函数的用法和一些例子》update()方法是字典对象的方法,用于将一个字典中的键值对更新到另一个字典中,:本文主要介绍python中update()函数的用法和一些... 目录前言用法注意事项示例示例 1: 使用另一个字典来更新示例 2: 使用可迭代对象来更新示例 3: 使用

C#异步编程ConfigureAwait的使用小结

《C#异步编程ConfigureAwait的使用小结》本文介绍了异步编程在GUI和服务器端应用的优势,详细的介绍了async和await的关键作用,通过实例解析了在UI线程正确使用await.Conf... 异步编程是并发的一种形式,它有两大好处:对于面向终端用户的GUI程序,提高了响应能力对于服务器端应

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.