Fundamental use of functions
Keyword: func
func hello(name:String) ->String { let result = "Hello,"+name return result } hello(name: "imagine")
Lectotype:
func hello(name:String?,greet:String) ->String { let result = greet+","+(name)! return result } var nickname:String? //nil nickname = "imagine" hello(name: nickname,greet: "Good Night") //Good Night,imagine"
No parameter function, directly returns a function of string type:
func sayHello() ->String { return "Welcome to imaginecode" } sayHello() //"Welcome to imaginecode"
Empty type void / (), does not return any value
func sayVoid() ->Void{ print("it is a void func") }
Use tuples to get functions to return multiple values
func maxminScores( scores:[Int]) -> ( maxscore:Int,minscore:Int)? //Optional types of tuples { if scores.isEmpty{ return nil } var curmax = scores[0] ,curmin = scores[0] for score in scores[1..<scores.count]{ curmax = max(curmax, score) curmin = min(curmin, score) } return (curmax,curmin) } var scores:[Int]? = [12,60,71,81,91,100] //Optional array scores = scores ?? [] if let result = maxminScores(scores: scores!) { print(result.maxscore) print(result.minscore) }
Internal and external parameter names
func hello(userName nickname:String,greeting greet:String) -> String{ //Internal parameters nickname,greet, belong to function body let result = greet+":"+nickname return result } hello(userName: "imagine", greeting: "codeing") //External parameter names userName and greet ing are given to the parameters nickname and green
Default values of parameters
func hello(nickname:String,greet:String = "hello") -> String{ //Give greet the default value hello let result = greet+":"+nickname return result } hello(nickname: "imagine") //"hello:imagine"
func hello(nickname:String,greet:String = "hello",other:String = "nihao") -> String{ //Give greet the default value hello let result = greet+":"+nickname+other return result } hello(nickname: "imagine",other:"how do you do") //"hello:imaginehow do you do"
Variable parameters
- It's better for a function to have only one variable parameter, and that variable parameter can only be placed at the end of the function parameter list.
- Must parameter > default parameter > variable parameter
func add(a:Int,b:Int,others:Int ... ) ->Int //Other is a variable parameter... parse it into an array { var result = a + b for num in others { result += num } return result } var res = add(a: 2, b: 3) res = add(a: 2, b: 3, others: 4,5,6) NSLog(format: String, args: CVarArg...) //CvarArg is also a variable parameter
inout parameter - Reference passing
- inout is used to declare that data is passed by address, also known as reference transfer.
- The parameters modified by inout can not have default values, and the set of parameters with range can not be modified.
- Once a parameter is modified by inout, it can no longer be modified by var and let.
func swapTwoInts( a:inout Int,b:inout Int) { let t = a; a = b b = t } var x = 0, y = 100 swapTwoInts(a: &x, b: &y) //Input reference parameters
Function type
func add(a:Int,b:Int) -> Int { return a+b } let anotherAdd:(Int,Int)->Int = add //The parameter is two Ints, the return type is Int, and add is a variable anotherAdd(3,4)
func changeScores1(scores:inout [Int]) { for i in 0..<scores.count { scores[i] = Int(sqrt(Double(scores[i]))*10) } } func changeScores2(scores:inout [Int]) { for i in 0..<scores.count { scores[i] = Int(sqrt(Double(scores[i]))/150.0 * 100.0) } } func changeScores3(scores:inout [Int]) { for i in 0..<scores.count { scores[i] += 3 } } var scores1 = [20,40,60,80,90] changeScores1(scores: &scores1) var scores2 = [20,40,60,80,90] changeScores2(scores: &scores2) var scores3 = [20,40,60,80,90] changeScores3(scores: &scores3)
Improvement:
func changeScores(op:(Int)->Int, scores:inout [Int]) { for i in 0..<scores.count{ scores[i] = op(scores[i]) } } func op1(x:Int)->Int {return Int(sqrt(Double(x))*10)} func op2(x:Int)->Int {return Int(sqrt(Double(x))/150.0*100.0)} func op3(x:Int)->Int {return x + 3} var scores1 = [20,40,60,80,90] changeScores(op: op1, scores: &scores1) var scores2 = [20,40,60,80,90] changeScores(op: op2, scores: &scores2) var scores3 = [20,40,60,80,90] changeScores(op: op3, scores: &scores3)
var arr = [Int]() for _ in 1...20 { arr.append(Int(arc4random()%100)) } arr func compareTwoInts(a:Int,b:Int) -> Bool{return a>b } arr.sort()
Return function type return value, function nesting
//Postage func mailcost1(weight:Int) -> Int { return 1*weight } func mailcost2(weight:Int) -> Int { return 2*weight } func chooseMailCostMethod(weight:Int) -> (Int)->Int //Returns an Int-type function, decoupling { return weight <= 10 ? mailcost1 : mailcost2 } func totalCost(price:Int,weight:Int) -> Int { let mailCost:(Int)->Int = chooseMailCostMethod(weight: weight) return mailCost(weight) + price*weight }
Another way of writing: function nesting
func mailcost1(weight:Int) -> Int { return 1*weight } func mailcost2(weight:Int) -> Int { return 2*weight } func totalCost(price:Int,weight:Int) -> Int { func chooseMailCostMethod(weight:Int) -> (Int)->Int //Function nesting { return weight <= 10 ? mailcost1 : mailcost2 } let mailCost:(Int)->Int = chooseMailCostMethod(weight: weight) return mailCost(weight) + price*weight }