swift学习笔记6

都希望拥有一个既有长度又有厚度的人生

有多少人能在眼花缭乱的纷繁世界下,理智的区应对?

又有几个人能将一件事坚持做10年?

想走在前面,需要明智的选择和坚守的恒心,也需要智慧和高效的自我管理!

六、函数和闭包

函数: 执行特定任务的一段代码

目的是复用,或者嵌套。

闭包:匿名函数,可以作为表达式,函数参数,函数返回值,让程序更简洁。

声明函数  func

无返回值的3种声明方式

 1、省略 ->返回值类型

2、->() 空

3、->void 

谁调用函数,谁负责给形参赋值。

func max(x:Int,y:Int)->Int

{

var z = x>y?x:y

return z

}

func sayHi(name:String)->String

{

return "(name),你好!"

}

调用

var a = 6 ,b=5

var result = max(a,b)

println(sayHi("renhairui"))

实战:定义个函数,返回指定的Double数值整数部分和2位小数部分

func divide(num:Double)->(String,String)

{

var zheng = Int64(num)

var xiao = round((num-Double(zheng))*100)

return ("(zheng)","(xiao)")

}

调用

var test = divide(123.456)

println("整数:(test.0),小数:(test.1)")

实战 找出数组中最大,最小值

func getMaxAndMin(nums:[Int])->(max:Int,min:Int)

{
var max = nums[0],min = nums[0]

for num in nums

{

if num>max {

max = num

}

if num <min{

min = num

}

}

return (max,min)

}

调用

var nums = [20,30,5,89,100,2,6,-1]

var result = getMaxAndMin(nums)

println("最大值为:(result.max),最小值为:(result.min)")

递归函数:函数中调用自身,隐式循环,重复执行某一段代码

实战  已知数列 f(0) = 1,f(1) = 4,f(n+2) = 2*f(n+1) +f(n)

  func fn(n:Int)->Int

{
if n == 0{

return 1

}else if n ==1{

return 4

}else{

return 2*fn(n-1)+fn(n-2)

}

}

递归是非常有用的,遍历某个路径下的所有文件,且深度是未知的。

外部形参

func girth(#Double,#height:Double)->Double

{

return Double(2)*(width+height)

}

调用

println(girth(12,height:22.5))

形参默认值

#height:Double = 20.3

println(girth(12))

取消默认值形参的外部参数名

_ height:Double = 20.3

可变形参,放在参数表最后

func test (a:Int,books:String ...)

{

for temp in books

{

println(temp)

}

println(a)

}

test(3,"swift","renhairui","ok")

变量形参  func girth(var #Double,#height:Double)->Double

{

width = (width + height)*2

return width

}

// 避免函数体内 重新定义新变量

调用

var w = 3.2

println(girth(w,height:12.9))

println(w)  // 3.2

inout 形参

函数体内可以修改 参数的值 

func swap(inout a:Int,inout b:Int)

{

let tmp = a 

a = b

b = temp

}

&对参数进行赋值才行, 

调用

var a = 6 ,b= 9

swap(&a,&b)

已经实现交换!

实质:强制传递变量指针。

不管是值类型的参数还是引用类型的参数,swift 都只是将参数的副本传入函数内, 值类型参数传递-->值本身副本

引用类型参数传递-->引用的副本

函数类型

var myfun:(Int,Int)->Int   // 类型是 (Int,Int)->Int

  一般会把一个函数复制给它  变量类型要一致

函数类型的形参就是在调用函数时,动态传入函数,命令模式!

函数类型可以作为返回值类型

实战 

func square(val:Int)->Int

{

return  val * val 

}

func cube (val:Int)->Int

{

return val* val *val

}

// 计算阶乘

func factorial (val:Int)->Int

{

var result = 1

for index in 2...val

{

result *=index

}

return result

}

定义函数:返回值类型 (Int)->Int

func getMathFunc (#type:String)->(Int)->Int

{

switch(type)

{

case "sqsuare":

return square

case "cube":

return cube

defalut:

return factorial

}

}

调用

var mathFunc = getMathFunc (tpye:"cube")

// 输出  125

println(mathFunc(5))

mathFunc = getMathFunc(type:"other")

println(mathFunc(5)) //120

函数重载  多个同名函数,只是参数表,返回值类型不同

闭包

1、无func   无函数名

2、使用in关键字(可省略)

3、第一个花括号,移动到形参表的圆括号之前

4、省略return

5、省略参数名

6、$0  $1代表参数

var square:(Int)->Int = {$0*$1}

println(square(5))

// 25

尾随闭包  trailing closure  如果调用函数的最后一个参数是闭包,就将{}提出来放在最后

someFunc (20,{})   这种--> someFunc(20){}

func map (var #data:[Int],#fn:(Int)->Int)->[Int]

{

for var i= 0, len = data.count;i<len:i++

{

data[i] = fn(data[i])

}

return data

}

var dataArr = [3,4,6,5,7]

var rvt1 = map(data:dataArr){$0*$0}  // 计算元素平方

var rvt2 = map(data:dataArr){$0*$0*$0}  //计算元素立方

// 计算元素阶乘   不能省略return

var rvt3 = map(data:dataArr){
var result = 1

for index in 2...$0

{

result * = index

}

return result
}

捕获  :闭包 可以访问或修改上下文中的变量和常量(只能访问不能修改)

即使作用域不存在也没关系

常用于 嵌套函数中

func makeArray(ele:String)->()->[String]

{

var arr:[String]=[]

func addElement() ->[String]

{
arr.append(ele)

return arr

}

}

上边代码中 arr ,ele捕捉了上下文中的变量,每个闭包会持有一个它捕获的变量副本

调用

let addBody = makeArray("renhairui") 

println(addBody) // [renhairui]

println(addBody) //[renhairui,renhairui]

let addOther = makeArray("孙悟空")

println(addOther) // [孙悟空]

println(addOther) // [孙悟空,孙悟空]

输出是两个孙悟空

闭包是引用类型,所以,把一个闭包复制给两个引用变量时,程序并不会复制他们,让他们都指向同一个闭包

let addTest = addOther

println(addTest)// [孙悟空,孙悟空,孙悟空]

println(addTest)// [孙悟空,孙悟空,孙悟空,孙悟空]

原文地址:https://www.cnblogs.com/heri/p/4471846.html