import Foundation //func 函数名(形参: 形参类型) -> 返回类型 //MARK:----------1.函数定义----------- //单参数 func sayHello(name: String) -> String { return "Hello again," + name + "!" } //函数调用 print(sayHello("小红")) //多参数 func sub(a: Int,b: Int) -> Int { return b - a } print(sub(1,b: 10)) //无参数 func sayHelloWorld() -> String { return "hello,world" } print(sayHelloWorld()) // prints "hello,world” //无返回值 func sayGoodbye(personName: String) { print("Goodbye,\(personName)!") } sayGoodbye("小红") // prints "Goodbye,小红!” //1.3.1被调用时,一个函数的返回值可以被忽略 func printAndCount(str: String) -> Int { print(str) return str.characters.count //定义了有返回值的函数必须返回一个值 } func printWithoutCounting(str: String) { printAndCount(str) //printAndCount 函数的返回值可以被忽略 } printAndCount("hello,world") printWithoutCounting("hello,world") //1.4多重返回值函数(Functions with Multiple Return Values) //你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回 func count(string: String) -> (vs: Int,cs: Int,os: Int) { var vowels = 0,consonants = 0,others = 0 for character in string.characters { 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!") print("\(total.vs) 元音字母 and \(total.cs) 辅音字母") // prints "6 vowels and 13 consonants” //MARK:-------2.参数名--------- //2.1外部参数名 func someFunction(name: String,age:Int) { } someFunction("John",age: 20) //2.3默认参数值(Default Parameter Values) //你可以在函数体中为每个参数定义默认值。当默认值被定义后,调用这个函数时可以略去这个参数 func join(string s1: String,toString s2: String,withJoiner joiner: String = " ") -> String { return s1 + joiner + s2 } //1、指定第三个参数 let str1 = join(string: "hello",toString: "world",withJoiner: "-") print("str1:"+str1) // returns "str1:hello-world" //2、不指定参数,将使用默认值 let str2 = join(string: "hello",toString:"world") print("str2:"+str2) // returns "str2:hello-world" //MARK:---------3.可变参数------------ //一个函数最多能有一个可变参数 //可变参数必须放在参数表中最后的位置 //求所有数的平均值 func arithmeticMean(numbers: Double...) -> Double { var sum: Double = 0 for i in numbers { sum += i } return sum / Double(numbers.count) } print(arithmeticMean(1,2,3,4,5)) print(arithmeticMean(3,8,19)) //MARK:-----------4.常量参数和变量参数------------ //通过在参数名前加关键字 var 来定义变量参数 func changeString(var name: String,i: Int,char: Character) -> String { let number = i - name.characters.count for _ in 1...number { //在字符串的前面添加字符(char) name.insert(char,atIndex: name.startIndex) // name = char + name } return name } let string1 = "hello" let string2 = changeString(string1,i: 10,char: "-") print("string1:" + string1) print("string2:" + string2) //MARK---------5.输入输出参数---------- /* 定义一个输入输出参数时,在参数定义前加 inout 关键字 输入输出参数不能有默认值,而且可变参数不能用 inout 标记。如果你用 inout 标记一个参数,这个参数不能被 var 或者 let 标记。 */ //交换a和b的值 func changeAandB(inout a: Int,inout b: Int) { let tempA = a a = b b = tempA } //只能传入一个变量作为输入输出参数 var a = 3 var b = 107 //当传入的参数作为输入输出参数时,需要在参数前加&符,表示这个值可以被函数修改 changeAandB(&a,b: &b) print("a现在是 \(a),and b现在是 \(b)") //MARK:------6.函数类型------------ //(是一种数据类型,类似 C语言函数指针、OC语言的Block) //分三步:1、定义函数;2、声明函数类型变量或常量;3、给函数类型变量赋值 //1、定义函数 func sum(a: Int,b: Int) -> Int { return a + b } //2、声明函数类型变量 //3、给函数类型变量赋值 var mathFunc = sum //4、使用 print("Result: \(mathFunc(2,b: 3))") //6.1参数为函数 func printMathResult(mathFun: (Int,Int) -> Int,a: Int,b: Int) { print("Result: \(mathFun(a,b))") } printMathResult(sum,a: 3,b: 5) //6.2 返回值为函数 func add1(input: Int) -> Int { return input + 1 } func sub1(input: Int) -> Int { print("input: \(input)") return input - 1 } //返回函数类型 func chooseFunc(backValue: Bool) -> (Int) -> Int { return backValue ? sub1 : add1 } var ab = 3 //moveNearerTozero指向sub1 let moveNearerToZero = chooseFunc(ab > 0) //let moveNearerTozero:(Int) -> Int = chooseFunc(true) //原型 //moveNearerTozero = sub1 print(moveNearerToZero(10)) //9 //MARK:---------7.嵌套函数------------ //嵌套函数是对外界不可见的,但是可以被他的封闭函数(enclosing function)来调用。一个封闭函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用 //改写6.2 /* func chooseFunc(backValue: Bool) -> (Int) -> Int { func add1(input: Int) -> Int { return input + 1 } func sub1(input: Int) -> Int { return input - 1 } return backValue ? sub1 : add1 } var ab = 3 let moveNearerToZero = chooseFunc(ab > 0) print(moveNearerToZero(10)) //9 */ //8.闭包(Closures) /* 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Are Reference Types) */ //闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 lambdas 函数比较相似。 //MARK:------8.1 闭包表达式-------- //闭包表达式语法一般形式如下: /* { (parameters) -> returnType in statements } */ //闭包表达式语法可以使用常量、变量和inout类型作为参数,不提供默认值。 也可以在参数列表的最后使用可变参数。 元组也可以作为参数和返回值。 //不使用闭包 let names = ["Chris","Alex","Ewa","Barry","Daniella"] func backwards(s1: String,s2: String) -> Bool { return s1 > s2 } //用sort进行排序。E-D-C-B-A var reversed = names.sort(backwards) //print(reversed) //使用闭包 reversed = names.sort({ (s1: String,s2: String) -> Bool in return s1 > s2 }) reversed = names.sort({ s1,s2 in return s1 > s2 } ) //8.2 单表达式闭包隐式返回(Implicit Return From Single-Expression Clossures) //单行表达式闭包可以通过隐藏return关键字来隐式返回单行表达式的结果,如上版本的例子可以改写为: reversed = names.sort({s1,s2 in s1 > s2 }) //8.3 参数名称缩写(Shorthand Argument Names) //$0和$1表示闭包中第一个和第二个String类型的参数。 reversed = names.sort({ $0.0 > $1.0 } ) //8.4 运算符函数(Operator Functions) //Swift 的String类型定义了关于大于号 (>) 的字符串实现 reversed = names.sort(>) print(reversed) // reversed 为 ["Ewa","Daniella","Chris","Alex"] //8.5 尾随闭包(Trailing Closures) //如果您需要将一个很长的闭包表达式(以至于不能在一行中进行书写时)作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。 //如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把()省略掉。 func funcA(closure: () -> ()) { // 函数体部分 } //不使用尾随闭包进行函数调用 funcA({ // 闭包主体部分 }) //使用尾随闭包进行函数调用 funcA() { // 闭包主体部分 } reversed = names.sort { $0.0 > $1.0 } //将Int类型数组[16,58,510]转换为包含对应String类型的数组["OneSix","FiveEight","FiveOneZero"]: //字典 let digitNames = [ 0: "Zero",1: "One",2: "Two",3: "Three",4: "Four",5: "Five",6: "Six",7: "Seven",8: "Eight",9: "Nine" ] //数组 let numbers = [16,510] //number 为变量参数 let strings = numbers.map { (var number) -> String in var output = "" while number > 0 { //digitNames[]字典取值有可能出现取不到值的情况,所以返回一个可选值 (optional value) //对10取余,然后累加字符串 output = digitNames[number % 10]! + output //考虑百位数字,比如510的循环取值 number /= 10 } return output } print(strings) // strings 常量被推断为字符串类型数组,即 String[] // 其值为 ["OneSix","FiveOneZero"] //8.6 捕获值(Capturing Values) //闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。 func makeAddCount(forAddCount a: Int) -> () -> Int { var sum = 0 func addCount() -> Int { sum += a return sum } return addCount } let addByTen = makeAddCount(forAddCount: 10) //累加 print(addByTen()) print(addByTen()) print(addByTen()) let addBySeven = makeAddCount(forAddCount: 7) print(addBySeven()) print(addByTen()) //8.7 闭包是引用类型 let alsoAddByTen = addByTen print(alsoAddByTen()) // 返回的值为50