swift学习-函数

定义与调用

用func作为前缀来标志这是一个函数,用 (->) 加返回类型的名字表示该函数返回什么类型

func sayHelloAgain(personName: String) -> String {  
    return "Hello again, " + personName + "!"  
}  
println(sayHelloAgain("Anna"))  
// prints "Hello again, Anna!"  

参数与返回值

Swift中的函数的参数和返回值可以定义的非常灵活,包括从只带一个未命名的简单函数到复杂的带有表达式参数名和不同参数选项的复合函数.

  • 多个参数,写在圆括号中,用逗号分隔
func halfOpenRangeLength(start: Int, end: Int) -> Int {  
    return end - start  
}  
println(halfOpenRangeLength(1, 10))  
// prints "9" 
  • 无参,尽管没有参数,圆括号也不能省略,调用的时候也是函数名加圆括号
func sayHelloWorld() -> String {  
    return "hello, world"  
}  
println(sayHelloWorld())  
// prints "hello, world"  
  • 无返回值
    没有返回值就没有返回箭头和返回类型
func sayGoodbye(personName: String) {  
    println("Goodbye, \(personName)!")  
}  
sayGoodbye("Dave")  
// prints "Goodbye, Dave!"  
  • 多返回值
    用元组来让多个值作为一个复合值从函数中返回
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {  
    var vowels = 0, consonants = 0, others = 0  
    for character in string {  
        switch String(character).lowercaseString {  
        case "a", "e", "i", "o", "u":  
            ++vowels  
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",  
        "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":  
            ++consonants  
        default:  
            ++others  
        }  
    }  
    return (vowels, consonants, others)  
}    
let total = count("some arbitrary string!")  
println("\(total.vowels) vowels and \(total.consonants) consonants")  
// prints "6 vowels and 13 consonants"  

函数参数名

  • 函数的参数名只能在函数体内使用,称为局部参数名
func someFunction(parameterName: Int) {  
    // function body goes here, and can use parameterName  
    // to refer to the argument value for that parameter  
}  

外部参数名

  • 如果希望在函数调用的时候使用函数提供的参数的名字,就需要再定义一个外部参数名,写在局部参数名之前,空格分开
func someFunction(externalParameterName localParameterName: Int) {  
    // function body goes here, and can use localParameterName  
    // to refer to the argument value for that parameter  
}  
  • 以下是不使用和使用外部参数名的例子,其实代码执行是一样的,但是有了外部参数名,能让人比较直观的了解代码是要干什么的,增加可读性
func join(s1: String, s2: String, joiner: String) -> String {  
    return s1 + joiner + s2  
}  
join("hello", "world", ", ")  
// returns "hello, world"  
func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String {  
    return s1 + joiner + s2  
}  
join(string: "hello", toString: "world", withJoiner: ", ")  
// returns "hello, world"  

简写外部参数名

一个的简写方式,在参数名前加(#),告诉Swfit这个参数既作为外部参数,也作为局部参数

func containsCharacter(#string: String, #characterToFind: Character) -> Bool {  
    for character in string {  
        if character == characterToFind {  
            return true  
        }  
    }  
    return false  
}  
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")  
// containsAVee equals true, because "aardvark" contains a "v"  

默认参数

在函数定义的时候为每个参数定义默认值,当函数调用的时候可以略去这个参数

func join(string s1: String, toString s2: String,  
    withJoiner joiner: String = " ") -> String {  
        return s1 + joiner + s2  
}  
join(string: "hello", toString: "world", withJoiner: "-")  
// returns "hello-world"  
join(string: "hello", toString: "world")  
// returns "hello world" 

默认参数的外部参数名

func join(s1: String, s2: String, joiner: String = " ") -> String {  
    return s1 + joiner + s2  
}  
join("hello", "world", joiner: "-")  
// returns "hello-world"  

可变参数

函数调用时,如果不确定参数的数量,通过在变量类型后面加 (...) 定义可变参数,一个函数最多能有一个可变参数,且必须是函数表中最后的一个,避免函数调用时出现歧义,所以一个函数如果有一个或多个带默认值的参数,还有一个可变参数,千万把可变参数放在最后

func arithmeticMean(numbers: Double...) -> Double {  
    var total: Double = 0  
    for number in numbers {  
        total += number  
    }  
    return total / Double(numbers.count)  
}  
arithmeticMean(1, 2, 3, 4, 5)  
// returns 3.0, which is the arithmetic mean of these five numbers  
arithmeticMean(3, 8, 19)  
// returns 10.0, which is the arithmetic mean of these three numbers  

常量参数和变量参数

函数参数默认都是常量,想在函数体内更改参数值将会报错,但有时候,会在函数中有传入参数的变量值副本,通过指定一个或多个参数作为变量参数参数,从而避免在函数中定义新的变量,通过在参数名前加var来定义变量参数

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

alignRight函数将参数string定义为变量参数,意味着string作为一个局部变量,用传入的字符串值初始化,并在函数体中进行操作,但也仅仅存在于函数调用的生命周期内

输入输出参数

如果想要一个函数可以修改参数的值,并且这些修改在函数结束调用后仍然存在,那就可以定义为输入输出参数,在参数前面添加inout关键字,这个值被函数修改后被传出函数,并替换原来的值,同时,传入的只能是变量而不能是常量,当传入的参数作为作为输入输出参数时,需要在参数面前加 & 符号,表示这个值可以被修改

func swapTwoInts(inout a: Int, inout b: Int) {  
    let temporaryA = a  
    a = b  
    b = temporaryA  
}  
var someInt = 3  
var anotherInt = 107  
swapTwoInts(&someInt, &anotherInt)  
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")  
// prints "someInt is now 107, and anotherInt is now 3"  

函数类型

每个函数都有特定的函数类型,由参数类型和返回类型组成

func addTwoInts(a: Int, b: Int) -> Int {  
    return a + b  
}  
func multiplyTwoInts(a: Int, b: Int) -> Int {  
    return a * b  
}  
// 以上两个的函数类型是 (Int, Int) -> Int  
func printHelloWorld() {  
    println("hello, world")  
}  
// 这个函数类型是 () -> ()  

使用函数类型

  • 使用函数类型就跟使用其他类型一样,比如可以定义一个常量或变量,类型就是函数,而且可以给这个函数赋值
    以下定义一个mathFunction的变量,类型是 两个int型参数并返回int型的函数,并让这个变量指向addTwoInts函数
var mathFunction: (Int, Int) -> Int = addTwoInts  
println("Result: \(mathFunction(2, 3))")  
// prints "Result: 5"  
  • 有相同参数类型且返回类型相同的不同函数可以赋值给同一个变量
mathFunction = multiplyTwoInts  
println("Result: \(mathFunction(2, 3))")  
// prints "Result: 6"  
  • 在赋一个函数给常量或变量时,可以省略函数类型
let anotherMathFunction = addTwoInts  
// anotherMathFunction is inferred to be of type (Int, Int) -> Int  

函数类型作为参数类型

用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数,将函数的一部分实现交给函数的调用者

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {  
    println("Result: \(mathFunction(a, b))")  
}  
printMathResult(addTwoInts, 3, 5)  
// prints "Result: 8" 

函数类型作为返回类型

在返回箭头 (->) 后写一个完整的函数类型,表示将函数类型作为另一个函数的返回类型

func stepForward(input: Int) -> Int {  
    return input + 1  
}  
func stepBackward(input: Int) -> Int {  
    return input - 1  
}  
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {  
    return backwards ? stepBackward : stepForward  
}  
var currentValue = 3  
let moveNearerToZero = chooseStepFunction(currentValue > 0)  
// moveNearerToZero now refers to the stepBackward() function  
println("Counting to zero:")  
// Counting to zero:  
while currentValue != 0 {  
    println("\(currentValue)... ")  
    currentValue = moveNearerToZero(currentValue)  
}  
println("zero!")  
// 3...  
// 2...  
// 1...  
// zero!  

嵌套函数

定义在全局域中的称为全局函数,将函数定义在别的函数中,称为嵌套函数

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {  
    func stepForward(input: Int) -> Int { return input + 1 }  
    func stepBackward(input: Int) -> Int { return input - 1 }  
    return backwards ? stepBackward : stepForward  
}  
var currentValue = -4  
let moveNearerToZero = chooseStepFunction(currentValue > 0)  
// moveNearerToZero now refers to the nested stepForward() function  
while currentValue != 0 {  
    println("\(currentValue)... ")  
    currentValue = moveNearerToZero(currentValue)  
}  
println("zero!")  
// -4...  
// -3...  
// -2...  
// -1...  
// zero!  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容