swift-函数

函数可以说是在编程语言中非常重要的一种语法类型,swift中,由于函数的语法与方法基本相同,所以从学习函数的语法开始来了解方法。

使用func来声明一个函数,使用名字和参数来调用函数。使用->来指定函数的返回值的类型。

func greet(name: String, day:String) -> String {
    return "Hello \(name), today is \(day)"
}
greet("Bob", "Monday")

函数可以有多个返回值,使用元祖来使函数返回多个值。该元祖的元素可以用名字或数字来表示。

func calculateStatistics(scores: [Int]) -> (min: Int,           max: Int, sum: Int) {
    var min = score[0]
    var max = score[0]
    var sum = 0
    
    for score in scores {
        if  min > score {
              min = score
        } else if max < score {
              max = score
        }
        sum += score
    }
    
    return (min, max, sum)
}
let statistics = calculateStatisctics([2, 100, 30, 14, 89])
print(statistics.sum)
print(statistics.max)

此外函数还可以带一个可变个数的参数,这个参数在函数内表现为数组的形式:

func numOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42, 192, 63)

注意一个函数最多只能有一个可变参数。

函数还可以嵌套。被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。

 func returnFifteen() -> Int { var y = 10
     func add() { 
        y += 5
     } 
    add() 
    return y
 }
returnFifteen()

函数是第一等类型,这意味着函数可以作为另一个函数的返回值。

func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
           return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

函数也可以当做参数传给另一个函数。

func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 8, 23]
hasAnyMatches(numbers, condition: lessThanTen)

函数实际上是一种特殊的闭包:它是一段能之后调用的代码。闭包中的代码能访问闭包所建作用域中能得到的变量和函数,即使闭包是在一个不同的作用域中被执行 - 你已经在嵌套函数例子中所看到。你可以使用{}来创建一个匿名闭包。使用in将参数和返回值类型声明与闭包函数体进行分离。

numbers.map ({
    (number: Int) -> Int in
    let result = 3 * number
    return number
})

有很多种创建更简洁的闭包的方法。如果一个闭包的类型已知,比如作为一个回调函数,你可以忽略参数的类型和返回值。单个语句闭包会把它语句的值当做结果返回。

let mappedNumbers = number.map({ number in 3 * number })
print (mappedNumbers)

你可以通过参数位置而不是参数名字来引用参数--这个方法在非常短的闭包中非常有用。当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面。当一个闭包是传给函数的唯一参数,你可以完全忽略括号。

let sortedNumbers = number.sort{ $0 > $1 }
print(sortedNumbers)

变量参数和常量参数

函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。

但是,有时候,如果函数中有传入参数的变量值副本将是很有用的。你可以通过指定一个或多个参数为变量参数,从而避免自己在函数中定义新的变量。变量参数不是常量,你可以在函数中把它当做新的可修改副本来使用。

通过在参数名前加关键字var 来定义变量参数:

func alignRight(var string: String, totalLength: Int, pad: Character) -> String { 
    let amountToPad = totalLength - string.characters.count 
    if amountToPad < 1 {
         return string 
    }
    let padString = String(pad) 
    for _ in 1...amountToPad {
        string = padString + string 
    }
    return string
}
let originalString = "hello" 
let paddedString = alignRight(originalString, totalLength: 10, pad: "-") 
// paddedString is equal to "-----hello" 
// originalString is still equal to "hello"

这个例子中定义了一个叫做 alignRight(_:totalLength:pad:) 的新函数,用来将输入的字符串对齐到更长的输出字符串的右边缘。左侧空余的地方用指定的填充字符填充。这个例子中,字符串"hello" 被转换成了"-----hello"

alignRight(_:totalLength:pad:)函数将输入参数string定义为变量参数。这意味着string现在可以作为一个局部变量,被传入的字符串值初始化,并且可以在函数体中进行操作。

函数首先计算出有多少字符需要被添加到string的左边,从而将其在整个字符串中右对齐。这个值存储在一个称为amountToPad的本地常量。如果不需要填充(也就是说, 如果amountToPad小于1),该函数简单地返回没有任何填充的输入值string

否则,该函数用pad字符创建一个叫做padString的临时String 常量,并将amountToPadpadString添加到现有字符串的左边。(一个String值不能被添加到一个Character值上,所以padString常量用于确保+操作符两侧都是String值)。

注意
对变量参数所进行的修改在函数调用结束后便消失了,并且对于函数体外是不可见的。变量参数仅仅存在于函数 调用的生命周期中。


输入输出参数

变量参数,正如上面所述,仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数。

定义一个输入输出参数时,在参数定义前加inout关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。

你只能传递变量给输入输出参数。你不能传入常量或者字面量(literal value),因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加&符,表示这个值可以被函数修改。

注意
输入输出参数不能有默认值,而且可变参数不能用inout标记。如果你用inout标记一个参数,这个参数不能被var或者let标记。

下面是例子,swapTwoInts(_:_:)函数,有两个分别叫做ab的输入输出参数:

func swapTwoInts(inout a: Int, inout _ b: Int) {
    let temporaryA = a
    a= b
    b = temporaryA
}

这个swapTwoInts(_:_:)函数简单的交换ab的值。该函数先将a的值存到一个临时变量temporaryA中,然后将b的值赋给a,最后将temporaryA的值赋给b

你可以用两个Int型变量来调用swapTwoInts(_:_:)。需要注意的是someIntanotherInt在传入swapTwoInts(_:_:)函数前,都加了&的前缀。

var someInt = 3 
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt) 
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"```

从上面的例子中,我们可以看到```someInt```和```anotherInt```的原始值在```swapTwoInts(_:_:)```函数中被修改,尽管他们的定义在函数体外。
>注意
输入输出参数和返回值是不一样的。上面的```swapTwoInts```函数并没有定义任何返回值,但仍然修改了```someInt```和```anotherInt```的值。输入输出参数是函数对函数体外产生影响的另一种方式。

你可能感兴趣的:(swift-函数)