• 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())

  • 相关阅读:
    Mandriva Flash: 到处可用的口袋 Linux
    Pidgin 衔接 Google Talk 的设置配备铺排
    5 个使 Vim 更易用的脚本
    Bash 运用才干大补贴
    915Resolution打点宽屏表现标题问题
    Linux下误删root目次
    惠普推出 Linux 迷你条记本
    weblogic8.1for linux ES3.0拆卸与设置
    英俊的 Linux Mini PC
    Zonbu-售价 99 美元的袖珍电脑
  • 原文地址:https://www.cnblogs.com/chebaodaren/p/5501563.html
Copyright © 2020-2023  润新知