2019年6月3日 星期一

fuction

定義function
func 自訂func名稱(參數1:資料類型, 參數2:資料類型, 參數3:資料類型) -> 傳出值資料類型{
    code
    return type
}
參數可以省略,return type也可空白!
呼叫function
let 接收物 = 自訂func名稱(引數1, 引數2, 引數3)

func greet(person:String) -> String {
    let greeting = "Hello, " + person + "!";
    return greeting
}
print(greet(person: "Anna"));
print(greet(person:"Brian"));

func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}

print(greetAgain(person: "Anna"));

global Function:
apple 定義,使用者只呼叫

func greet(person:String) -> String{
    let greeting = "Hello, " + person +"!";
    return greeting;
}
func greetAgain(person:String) -> String{
    return "Hello again, " + person +"!";
}
//function 沒有參數
//function 有傳出,就一定要有return!
func sayHelloWorld() -> String {
    return "Hello, World";
}
//function 有多個參數
//function名稱相同,但參數名稱不同,或參數名稱相同,但參數的數量不同,皆視為不同的function
func greet(person:String, alreadyGreeted:Bool) -> Stringh{
    if alreadyGreeted {
        return greetAgain(person: String);
    }
}
print(greet(person: "Tim", alreadyGreeted: true));

//function 沒有return值
//func greet(person:String) -> Void { },-> Void:表示沒有傳出值!
func greet(person1:String){
    print("Hello, \(person1)");
}
func printAndCount(string:String) -> Int{
    print(string);
    return string.count;
}
func printWithoutCounting(string:String){
    let _ = printAndCount(string:string);
}
printWithoutCountin(string: "Hello, World!");

//利用tuple傳出多個值
func minMax(array:[Int]) -> (min:Int,max:Int){
    var currentMin = array[0];
    var currentMax = array[0];
    for value in array[1..<array.count]{
        if value < currentMin{
            currentMin = value;
        } else if value > currentMax{
            currentMax = value;
        }
    }
    return (currentmin,currentMax);
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71]);
bounds.max
bounds.min

//optional的寫法
func minMax(array:[Int]) -> (min:Int,max:Int)?{
    if array.isEmpty {
    return nil;
    }
    var currentMin = array[0];
    var currentMax = array[0];
    for value in array[1..<array.count]{
        if value < currentMin{
            currentMin = value;
        } else if value > currentMax{
            currentMax = value;
        }
    }
    return (currentmin,currentMax);
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]){
    bounds.max;
    bounds.min;
}
//function的引數與參數名稱,
func someFunction(firstParameterName:Int, secondParameterName:Int){
 
}
someFunction(firstParameterName: 3, secondParameterName:2)
//自訂引數名稱 argumentLabel ,parameterName是參數名稱
func someFunction(argumentLabel parameterName:Int){
 
}

someFunction(argumentLabel: 54);

func greet(person:String, from hometown:String) -> String{
    return "Hello \(person)! Glad you could visit from \(hometown)"
}
greet(person: "Bill", form: "Cupertino");

//省略引數名稱
func someFunction(_ firstParameterName:Int, secondParamaterName:Int){

}
someFunction(5, secondParamaterName:3)

//default parameter value,有default value的參數要寫在後面!
func someFunction(parameterWithoutDefault:Int,patameterWithDefault:Int = 12){
 
}
someFunction(parameterWithoutDefault: 3, patameterWithDefault: 6)
someFunction(parameterWithoutDefault: 5)

//不限參數數量,這時引述名稱大多省略!參數內容則為陣列!
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,6)
arithmeticMean(1.4,6,8,4.6,7.8)

//inout parameter,參數值為常數(let),無法變更!要在function內變更已設定的參數值,需用inout!
func swapTwoInt(_ a:inout Int, _ b:inout Int){
    let temporaryA = a;
    a = b;
    b = temporaryA;
}

var someInt = 3;
var anotherInt = 107;
//inout參數的呼叫,名稱前會多&
swap(&someInt, &anotherInt);
someInt;
anotherInt;

//function type,不管function名稱,只管參數和return值
//function type可以被存在變數,可以當作引數,可以當return type
func addTwoInts(_ a:Int, _ b:Int) -> Int{
    return a + b;
}

func mutiplyTwoInts(_ a:Int, _ b:Int) -> Int{
    return a * b;
}

func printHelloWorld(){
    print("hello, world");
}
//func printHelloWorld()的function type表示法:() -> Void

//將func addTwoInts指定給變數mathFunction,mathFunction的資料類型是function type:(Int, Int) -> Int
var mathFunction:(Int, Int) -> Int = addTwoInts;
print("result:\(mathFunction(2,3))");
mathFunction = mutiplyTwoInts
print("result:\(mathFunction(2, 3))");

//把function當作參數
func printMathResult(_ mathFunction:(Int, Int) -> Int, _ a:Int, _ b:Int) {
    print("Result:\(mathFunction(a,b))")
}
printMathResult(addTwoInts, 3, 5);

Nested Function
//Nested Function
//傳出function
func chooseStepFunction(backward:Bool) -> (Int) -> Int{
    func stepForward(input:Int) -> Int{
        return input + 1
    }
   
    func stepBackward(input:Int) -> Int{
        return input - 1
    }
    //三元運算式 Bool ?true的運算:false的運算
    //下列只是傳出function,不是執行function,所以只輸入function名稱,沒有()!
    return backward ? stepBackward : stepForward
}

var currentValue = -4;
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)

while currentValue != 0 {
    print("\(currentValue)...");
    currentValue = moveNearerToZero(currentValue)
}

Closure(閉鎖)--> 匿名的Function
用在當一個function的參數需求是一個function時,可以直接closure的方式給予。
Closure呼叫時語法:
mainFunction({
    (參數名:資料類型,參數名:資料類型) -> return typr in
    coding................
    coding................
})

let names:[String] = ["Chris", "Alex", "Ewa", "Barry", "Daniella"];
let sotrdNames = names.sorted();
//定義一個function,省略參數名稱
func backward(_ s1:String,_ s2:String) -> Bool{
    return s1 > s2;
}
//func sorted(by: (Element, Element) -> Bool) -> [Element]
//Returns the elements of the sequence, sorted using the given predicate as the comparison between elements.
var reverseNames = names.sorted(by: backward)
//closure 標準寫法
reverseNames = names.sorted(by: {
    (s1:String, s2:String) -> Bool in
    return s1 < s2;
})
//closure 的所有資料類型,可以省略,因為透過推測
reverseNames = names.sorted(by: {
    (s1,s2) in
    return s1 < s2
})

//如果只有一行,可以省略return
reverseNames = names.sorted(by: {
    (s1,s2) in  s1 < s2
})

//s1,s2也可以省略去定義,用$0,$1替代
reverseNames = names.sorted(by: { $0 < $1 })
//連$0,$1都省略
reverseNames = names.sorted(by: < )

//trailing closure,在最後一 個參數
reverseNames = names.sorted(){
    $0 < $1;
}
//trailing closure,在最後一 個參數,連()都省略!
reverseNames = names.sorted{
    $0 < $1;
}
let numbers = [16, 58, 510];
let numberStrings = numbers.map({
    (n:Int) -> String in
    return String(n*2)
})