Swift -- 6.函数和闭包

函数

/*

函数分为函数名,参数,返回值,执行代码块四部分

有返回值函数可以作为一个值直接在print里输出 

*/

//函数定义

func max(a:Int, b:Int, c:Int) -> Int

{

    return 1

}

max(1, b: 2, c: 3)

func firstMethod(str:String) ->String

{

    return "123"

}

print(firstMethod("123"))

//没有返回值的函数

func noReturn(str:String)

{

    print("no return")

}

//多个返回值的函数

func mutableReturn(str:String) ->(String, String)

{

    return ("1", "2")

}

func mutableReturnWithName() ->(height:Int, weight:Int)

{

    return (1, 2)

}

var man = mutableReturnWithName()

print(man.height)

//函数调用本身  也就是递归

func doAgain(num:Int) -> String

{

    if num > 5{

        print("000")

        return "(doAgain(num - 1))"

    }else{

        return "fff"

    }

}

print(doAgain(10))

/*

递归是非常有用的,例如程序希望遍历某个路径下的所有文件,但这个路径下的文件夹的深度是未知的,那就可以使用递归来实现这个需求。系统可以设定一个函数,改函数接受一个文件路径作为参数,该参数可遍历出当前路径下的所有文件和文件路径--该函数再次调用函数本身来处理该路径下的所有文件路径

*/

/*

函数的参数

第一个参数如果不写外部参数,是不会显示外部参数的,第二个和之后的参数如果不写外部参数,会自动默认外部参数和内部参数同名

也就是说,除了第一个参数,其他的参数就算不设置外部参数也会有外部参数

*/

//拥有外部参数名的函数

func haveWaiName(wainame neiname:String) ->String

{

    print(neiname)

    return "(neiname)"

}

print(haveWaiName(wainame: "name"))

//外部形参名和内部形参名一样的函数

func havesameName(name name:String) ->String

{

    return name

}

print(havesameName(name: "sarah"))

//只有一部分形参有外部形参名的函数

func justSomehavename(name name:String, years:Int) -> (String, Int)

{

    return (name, years)

}

print(justSomehavename(name: "marry", years: 10).0)

//形参有默认值的函数 一般将带有默认值的形参放在最后面,下面这个并不是一个好的编程习惯

func valueAlready(user name:String = "marry", msg:String)

{

    print("(name),(msg)")

}

valueAlready(msg: "hi")

valueAlready(user: "tom", msg: "hi")

//参数个数可变的函数

func varibleValue(a:Int, books:String..., name:String)

{

    for tmp in books

    {

        print(tmp)

    }

}

varibleValue(3, books: "java","swift", name: "string")

/*

数量可变的参数的本质是一个数组参数,在执行代码块中当做一个数组来使用

*/

/*

函数中的形参默认是常量,如果想要变量的形参,需要自己声明

*/

func mutableNum(var name:String) ->String

{

    name = name + "sss"

    return name

}

print(mutableNum("mother"))

/*

在函数中,传入的参数如果是值类型,则传进去的是该值的副本,在函数中不会对原来的值产生影响

如果想要在函数中对该值进行改变,可以使用inout标签来标注

*/

func inoutFunc(inout age:Int) ->Int

{

    age = age + 1

    return age

}

var age = 5

print(age)//5

print(inoutFunc(&age))//6

print(age)//6

/*

当参数是引用类型的时候,程序会赋值引用的副本,不会复制该引用指向的对象

所以,当参数是引用类型的时候,即使不适用inout标签,该值仍然会在函数中被修改

但是,如果在函数中将引用类型置为空,只会切断副本和指向对象之间的联系,在函数之外,该值仍然不为空

*/

class DataWrap

{

    var a:Int = 0

    var b:Int = 0

}

func swap(var dw:DataWrap!)

{

    var tmp = dw.a

    dw.a = dw.b

    dw.b = tmp

    tmp = 0

    dw = nil

}

var wp:DataWrap! = DataWrap()

print(wp)

swap(wp)

print(wp)//wp没有被置为空,但是如果使用了inout标签,这里就会出错

//定义一个函数变量

var myfun : (Int, Int) ->Int //这里最好不要给参数命名,虽然也可以命名,但是在使用的时候系统不会提示

var test : (String) ->Void

func pow(base base:Int, exponent:Int) ->Int

{

    var result = 1

    for _ in 1...exponent

    {

        result *= base

    }

    return result

}

//将pow函数赋值给mufun,则myfun可以当成pow使用

myfun = pow

print(myfun(3,4))

/*

只要被赋值的函数类型与myfun的变量类型一致,程序就可以赋值成功

通过使用函数类型的变量,可以让myfun在不同的时间指向不同的函数,从而让程序更加灵活。

*/

//其中一个参数是函数的函数

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

{

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

    {

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

    }

    return data

}

func square(val:Int) ->Int

{

    return val*val

}

func cube(val:Int) ->Int

{

    return val*val*val

}

var data = [1,2,3]

print(map(data: data, fn: square))

print(map(data: data, fn: cube))

//这种方式可以动态的改变一个函数中的部分代码块,类似于c中的函数指针

//返回值为函数的函数

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

{

    switch(type)

    {

    case "square":

        return square

    default:

        return cube

    }

}

var mathFunc = getMathFunc(type: "cube")

print(mathFunc(5))

/*

函数重载

函数名相同,但是参数个数不同或外部参数名称不同或返回值不同

这种情况就是重载

*/

/*

嵌套函数

在swift中,函数和类享有同样的级别,函数可以直接声明在文件里,而不用单独声明在一个类里

所以,函数可以当成变量被引用,被返回,在函数中声明函数

*/

func getMathFunc2(type type:String) ->(Int) ->Int

{

    func square(val: Int) ->Int

    {

        return val*val

    }

    func cube(val:Int) ->Int

    {

        return val*val*val

    }

    switch(type)

    {

    case "square":

        return square

    default:

        return cube

    }

}

闭包

//本质是功能更灵活的代码块,可以直接作为返回值被返回

//在闭包里不要给参数写外部参数名,因为Xcode不会提示,还要自己写,很麻烦

var square3 = {

    (val:Int) -> Int in

    return val*val

}

print(square3(5))

//在闭包的后面添加圆括号来调用闭包

var resultt2 = {

    (base:Int,exponent:Int) -> Int in

    var result = 1

    for _ in 1...exponent

    {

        result *= base

    }

    return result

}(3, 4)

print(resultt2)

//省略形参类型,返回值类型的闭包

var square4:(Int) ->Int = {(val) in return val*val}

//省略了参数类型,参数列表的那个圆括号也可以省略

var square6:(Int) ->Int = {val in return val*val}

print(square6(5))

var result3:Int = {base, exponent in

    var result = 1

    for _ in 1...exponent

    {

        result *= base

    }

    return result

}(4, 3)//因为这个地方有声明int类型的变量,所以不用指定返回值类型

//上面两个闭包因为有声明闭包类型变量,所以也可以不声明返回值

//省略return

//如果闭包表达式的执行体只有一行代码,而且这行代码的返回值将作为闭包表达式的返回值,那么swift允许省略return关键字

var square7:(Int) ->Int = {val in val*val}

var square8 = {(val:Int) -> Int in val*val*val}

print(square7(3))

print(square8(3))

//省略形参名

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

var result4:Int = {

    var result = 1

    for _ in 1...$0

    {

        result *= $1

    }

    return result

}(3, 4)

//尾随闭包

//当函数的最后一个参数是一个函数类型的时候,可以用闭包来进行传参,然后把小括号放在闭包前面,把闭包给单独放置在外面

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

{

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

    {

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

    }

    return data

}

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

print("原数据(data2)")//"原数据[3, 4, 5, 6, 7] "

var rvt1 = map2(data: data2){$0 * $0}

var rvt3 = map2(data: data2){

    var result = 1

    for index in 2...$0

    {

        result *= index

    }

    return result

}

//如果调用函数时只需要闭包表达式一个参数,那么使用尾随闭包时,swift甚至允许程序省略调用函数的圆括号

//闭包可以捕获上下文中的变量和常量

//每个闭包都会持有一个它所捕获的变量的副本,所以,闭包执行与原来所在的函数并没有联系

//闭包是引用类型,所以即使是声明成常量也可以改变内部值

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

{

    var arr:[String] = []

    func addElement() ->[String]

    {

        arr.append(ele)

        return arr

    }

    return addElement

}

let add1 = makeArray("sun")

print(add1())

print(add1())

let add2 = makeArray("zhu")

print(add2())

print(add2())

原文地址:https://www.cnblogs.com/chebaodaren/p/5501563.html