函数是模块化编程的基本单位,将一组完成特定功能的代码“独立”地组成一个执行单位,称为函数。函数的基本结构如下所示:
其中,func为定义函数的关键字;“函数名”是调用函数的入口;每个函数可以有多个参数,即可以有多个“参数标签 参数名称:参数类型”,一般地,各个参数的标签不同,参数名称不能相同;当函数没有参数时,“()”必须保留;“函数返回类型”为函数返回值的类型,如果一个函数没有返回值,则省略“->函数返回类型”,此时返回空类型,即Void。函数本身也有类型,由其“(参数类型)->函数返回类型”表示。
一个函数可以作为另一个函数的参数,此时的函数可以写成无函数名的“闭包”形式。所谓闭包,是指由“{ }”包围的一组完成特定功能的代码。函数可视为带有函数名的特殊形式的闭包,而常用的闭包没有“函数名”,参数和返回类型均位于“{ }”内部,闭包类似于C++语言的Lambda函数。
#01、多返回值函数
从函数中返回多个值的方法有如下四种。
(1) 将元组作为函数的返回值,其典型语法如下:
上述函数语法中,返回值为一个包含两个元素的元组,这里元组的元素名可以省略。
(2) 将数组作为函数的返回值,其典型语法如下:
上述函数语法中,返回值为一个数组。
(3) 借助inout参数从函数中返回值,其典型语法如下:
上述函数语法中,虽然只有一个返回值,但是使用了inout参数,即定义的参数在“参数类型”前添加了inout关键字,表示该参数将直接使用传递给该参数的实参变量,在函数体内部对于inout型参数的修改,都将直接对传递给该参数的实参变量进行修改,从而可以通过inout参数实现从函数中返回值。注意,在调用带有inout参数的函数时,inout参数前需要添加“&”符号。
(4) 返回值为可选类型的函数,其典型语法如下:
上述函数在“返回值类型”后添加了一个“?”号,除了可以返回“返回值类型”指定的值外,还可以返回空值nil。
现在创建工程MyCh0001,包含程序文件main.swift和myfunc.swift,如程序段1和程序段1所示,下面借助工程MyCh0001介绍上述多返回值函数的用法。
程序段1程序文件myfunc.swift
程序段2程序文件main.swift
工程MyCh0001的执行结果如图1所示。
■ 图1 工程MyCh0403的执行结果
下面结合图1介绍工程MyCh0403的程序文件代码。
程序段1所示的程序文件myfunc.swift包含了5个函数,依次如下。
(1) 返回包含三个元素的元组的函数,如程序段1的第3~21行所示,这里将该函数代码再次罗列如下:
第3行定义了函数calc,具有一个可变个数参数,参数标签为list,参数名为val,返回值为包含三个Double型元素的元组类型。该函数借助元组可以返回三个Double型值。
第5行定义双精度浮点型变量m1、m2、m3和s,其中,m1用于保存数组的最小值,m2用于保存数组的最大值,m3用于保存数组的平均值,s用于保存数组所有元素的和。第6行将m1初始化为val[0],即数组val的首元素;将m2也初始化为val[0];将m3初始化为0;将s初始化为0。
第7~18行为一个for-in结构,计算数组val的全部元素和s、最小元素值m1和最大元素值m2。第19行计算数组val的平均值m3。第20行返回元组“(m1, m2, m3)”。
该函数的调用位于程序段4-7的第3行“let t1=calc(list:1,2,3,4,5,6,7,8,9,10)”,返回的t1为元组(1.0, 10.0, 5.5),即借助元组实现了多返回值。
(2) 返回值为带索引的元组类型的函数,如程序段4-6的第22~27行所示的minmax函数,将函数的代码再次罗列如下:
第22行定义了函数minmax,具有两个双精度浮点型的参数,返回值的类型为二元元组,这里为元组的每个元素指定了索引名称。第24行定义常量v1,将val1和val2的较小者赋给v1;第25行定义常量v2,将val1和val2的较大者赋给v2。第26行返回元组形式的v1和v2,即返回“(v1, v2)”。
该函数的调用位于程序段4-7的第5行“let t2=minmax(first:13.2, second:7.9)”,调用minmax得到一个元组t2,为(7.9, 13.2)。由于在上述定义函数minmax时为作为函数的返回值的元组的各个元素指定了索引名称,这里可以使用索引名称访问元组的元素,如程序段4-7的第6行“print("min=\(t2.min), max=\(t2.max)")”所示,使用t2.min访问元素t2.0,使用t2.max访问元素t2.1。
(3) 返回值类型为数组类型的函数,如程序段4-6的第28~36行的函数minmax,该函数的代码再次罗列如下:
第28行定义了函数minmax,具有一个数组类型的参数,参数标签为array,参数名为val,返回值类型为双精度浮点型的数组类型。第30行定义常量v1,赋值为val的最小值;第31行定义常量v2,赋值为val的最大值;第32行定义数组变量r,赋为空数组。第33行将v1添加到数组r中;第34行将v2添加到数组r中。第35行返回数组r。
上述函数的调用位于程序段4-7的第7行“let t3=minmax(array:[3.6,8.2,6.5,10.2,4.1,7.3])”,返回结果赋给t3,此时t3为包含两个元素的一维数组,即[3.6, 10.2]。
上述函数minmax具有一个缺点,没有考虑参数val为空数组的情况。在第30行和第31行中,v1和v2都有可能为空值nil,因此函数minmax的返回值有可能为空值nil。下面的函数修正了这点不足。
(4) 返回值为可选类型的函数,如程序段4-6中第37~44行所示的函数minmaxex,该函数的代码再次罗列如下:
第37行定义了函数minmaxex,返回值为“[Double]?”,表示这是一个可选类型,可以返回空值nil或双精度浮点型的数组。第39~42行为一个if结构,如果参数val为空数组,则第41行返回空值nil;否则,第43行返回函数minmax的返回值。
调用上述函数minmaxex的语句位于程序段4-7的第9~12行,该函数的代码再次罗列如下:
这里第9~12行为一个if结构,第9行使用了“iflet”形式的“可选绑定”方法,如果调用minmaxex返回nil,则第9行为假;否则,将minmaxex的返回值赋给t4。第11行输出结果“min=3.6, max=10.2”。
(5) 使用inout类型的参数的函数,如程序段4-6的第45~48行所示的函数swap,该函数的代码再次罗列如下:
第45行定义了函数swap,具有两个inout类型的参数,这类参数可使得传递给这类参数的实参变量进入函数内部参与运算,修改结果被保留在实参变量中。该函数只有第47行一条语句,即实现v1和v2交换数值。
函数swap的调用位于程序段4-7的第15行“swap(&v1,&v2)”,使用“&”放在实参变量的前面,其中,v1和v2为整型变量,初始值分别为5和9(见程序段4-7的第13行),执行“swap(&v1,&v2)”,v1和v2的值将依次为9和5,相当于借助inout参数返回了两个值。