都希望拥有一个既有长度又有厚度的人生
有多少人能在眼花缭乱的纷繁世界下,理智的区应对?
又有几个人能将一件事坚持做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(#width:Double,#height:Double)->Double
{
return Double(2)*(width+height)
}
调用
println(girth(width:12,height:22.5))
形参默认值
#height:Double = 20.3
println(girth(width: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 #width:Double,#height:Double)->Double
{
width = (width + height)*2
return width
}
// 避免函数体内 重新定义新变量
调用
var w = 3.2
println(girth(width: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)// [孙悟空,孙悟空,孙悟空,孙悟空]