🐼 SKNode and SKAction, put action in sequence
        // Run actions in sequence or in parallel, we have SKAction.sequence(..) and SKAction.group(..)
        // After node.run(..), the action run on different thread instead of main thread so it is async.
        // How can we make it run in the main thread, not sure..?
        // completion{..} will be called after all the actions finish.

        let act1 = SKAction.move(...)
        let act2 = SKAction.move(...)
        let sequence = SKAction.sequence([act1, act2], ...)
        node.run(sequence, completion:{
            print("act1 => act2 => completion")
        })
        
🐼 SKNode and SKAction, put action in group
        let act1 = SKAction.move(...)
        let act2 = SKAction.move(...)
        let group = SKAction.group([act1, act2], ...)
        node.run(group, completion:{
            print("act1 and act2 run as the SAME time")
        })
        
        // code example 
        if GameScene.lock == 0{
            GameScene.lock = 1
            let m1 = SKAction.move(to:CGPoint(x:100, y:0.0), duration:2.0)
            let m2 = SKAction.move(to:CGPoint(x:100, y:100), duration:2.0)

            let sequence = SKAction.sequence([m1, m2, SKAction.run {
                                    print("running{}")
                }])

            self.ballnode?.run(sequence, completion:{
                    GameScene.lock = 0
                })
        }
        
🐼 Swift Package Manager
        The tutorial will show you how to use package manager to build a command line tool
        0. Open your terminal 
        1. mkdir commandline
        2. cd commandline
        3. swift package init --type executable // --type => executable, not framework


        What is in the folder? 
        .gitignore      // Contain ./build Package and *.xcodeproj which will be ignored by git
        Package.swift   // which define your package, and all the dependency 
        README.md       // Read me file, nothing interesting
        Sources         // Source code dir, it contains main.swift
        Tests           // Unit test dir

        
🐼 Swift is the new language from Apple, is one of the best new program language out there.
        Apple finally released a new programming language called Swift in June 2014 and I finally have time to try it 
        out recently. In my opinion, Swift is the language that takes all the "good" stuffs from C/C++/Java/C# and 
        Haskell and put it into one BIG 🎁. I'm still pretty new to the language, but I found it is pretty easy to 
        get started if you are familliar Java/C/C++/C# or ƛ Haskell.
        Here are a few of many features that I like in Swift [4.1.2]

        0. The language is much cleaner [compare to Objective-C, Java and C++]
           Clean => [simple, short and concise] => sweet🍦
           No more semecolon, don't need bracket in if-and-else

        1. Functional style "almost" matches the King of functional lauguage: Haskell in some aspects.
           Swift adapts many functional style such as map, filter, reduce or fold, closure and lambda function etc.
           Closure can be passed as parameter in function and the syntax is clean. 
           If you still can remember how to pass block to function in Objective-C, then you will
           appreciate how sweet the syntax of closure is in Swift, please don't ask me how to pass
           function pointer to a function in C or C++.

        2. Optional instead of nil pointer
           Nil pointer check can be tedious and Optional can save your day with chaining.

        3. Array is awesome in Swift, it seems to me that 🍎 stole the syntax from Haskell again.
           Create and initialize array are dead simple in Swift, plus map, filter and reduce with closure 

        4. Swift finally adapts one of the very powerful feature in C++ or C#[if you are the MS guy/girl]: 
           Operator overloading => Java sucks. Operator overloading is very convenient for mathematical operation 
           such as Matrix, Complex Number and Vector etc.

        5. Pattern Matching
           Pattern matching is simple, powerful and elegant. The only way that you can feel the power is to use it. 

        6. Swift still keeps the OOP concept, and it can be very useful if you don't try to abuse it.
           Subclass, protocol/interface etc.

        7. Swift use the Default parameter for Contructor and Function like C++ 

        8. Swift use one of lovely feature from Objective-C is argument labels, 
           In other word, you can take overloading to the next level.

        Here are a few that I hate it in Swift.
        1. Swift use init method instead of contructor, I think the reason behind that is Objective-C using init() 
           But I can not come up any reason why Swift can not get rid of init()

        2. Closure CAN NOT modify inout(reference in C++) e.g.
           func myfun(num:inout Int){ 
                some closure...
                completion:{
                    num = 3    // get error, you need to pass by value instead of reference
                }
           }

        3. Coming soon 
        
Pass closure as parameter in Swift, and compute $\sum_{x=i}^{n} x $ and $\sum_{i}^{n} x^2$
        // pass clousre as parameter
        func fun(from:Int, to:Int, f:(Int)->(Int))->Int{
            var sum = 0
            for i in from..<to{
                sum += f(i)
            }
            return sum
        }
        let 𝚺:(Int)->(Int)={
            $0 
        }
        print(fun(from:1, to:4, f:𝚺)) // 6

        let δ:(Int)->(Int)={
            $0*$0
        }
        print(fun(from:1, to:4, f:δ)) // 16
        
😍 inout parameter in Swift
        Swift uses inout to tell programmer that parameter is passed by reference
        so that you can modify it inside the function and get the result outside of your function
        
        func fun(num:inout Int){
            num = 3
        }
        var num = 0
        fun(num:&num)
        print("num=(num)") // num=3
        
😍 Array is much easier to deal with than C/C++/Java/C#
        Array is one of the most frequently used data structure in modern programming language.
        C++ and Java make array initialization very painful.
        1. Swift make initialize array very easy (if you want to initialize array in C++/Java/C#, it is very painful)
            var array = []
            var array = [[]]
            var array = [Int]()             // create one dimensional array has length = 0
            let array = [1, 2, 3]           // initialize one dimensional array with 1, 2, 3
            let array = [[1, 2], [3, 4]]    // initialize two dimentional array with [1, 2] , [3, 4]
            let array = [MyClass(1), MyClass(2)]

            // In Swift
            let arr:[Int] = []
            let arr:[String] = []

            // In Haskell
            let arr = []::[Integer]
            let arr = []::[String]

        2. Create subarray from array
           let arr:Array<Int> = [1, 2, 3, 4, 5]
           let subarr = arr[1...4]          // subarr = [2, 3, 4]

        3. How Swift and Haskell handle range for array, => Haskell is much more elegant language
            // In Swift
            let arr = Array(1...4) 
            print(arr)

            // Haskell needs two dots:)
            let arr = [1..4]

        
🍑 Compare Two dimensional Array to Java
        // In Java
        int[][] array = {{}}
        int len = array.length; // 1
        array[0].length         // 0 

        // In Swift
        var array:[[Int]] = [[]]
        var len = array.count  // 1
        array[0].count         // 0 

        // In Java
        int[][] array = new int[0][0]
        int len = array.length; // 0 

        // In Swift
        var array = [[Int]]()
        var len = array.count  // 0 
        
🍑 filter, map, flatmap, reduce/fold(in Haskell) makes your life easier
        let array:Array = [1, 2, 3, 4]
        let subarr = array[1...3]

        let filter = array.filter{$0 > 4}

        let f1 = array.filter{$0 % 2 == 0}

        let reduce = array.reduce(0, {x, y in x + y})                    // ((((0 + 1) + 2) + 3 + 4) = 10

        let r1 = array.reduce(10, +) //   ((((10 + 1) + 2) + 3) + 4) = 20

        let p1 = array.reduce(1, *)  //   ((((1*1)*2)*3)*4 = 24

        let s1 = array.reduce(9, -)  //   (((((9-1)-2)-3)-4) = -1

        let arrays = ["Fibonacci", "Euler", "Albert Einstein"]
        let red1 = arrays.reduce("", +)

        let array2 = ["Golden Ratio", "Silver Ratio", "Copper Ratio"]
        let long = array2.reduce("⚽︎") {first, second in "\(first),\(second)"}

        // lambda function inside the reduce
        let sum = [1, 2].reduce(0){
            (acc:Int, next:Int)->Int in return acc + next
        }
        // Haskell way with foldr or foldl
        let sum = foldl(\x y -> x + y) 0 [1, 2] 

        let m1 = array.map{$0 * $0}

        let array2d = [[1, 2], [3, 4]]
        let collect = array2d.flatMap{ $0 } // [1, 2, 3, 4]
        
Map Iteration
        let map = [1:[1, 2, 3]]
        for m in map{
            for ar in m.value {
                print(ar)
            }
        }
        
Partition array with Set, Map and Filter
        let array = [2, 2, 3, 4, 3, 4]
        let group = Set(array).map{ v in return array.filter{$0 == v} }
        print("group=\(group)") // [[2, 2], [3, 3], [4, 4]]
        
🍑 Map, compute $ x \left[ \begin{array}{c} 1 \\ 2 \\ 3 \end{array} \right] $
        let list = [1, 2, 3]
        map{ x in return x*v } list
        
🍑 Map, Zip and Reduce, compute $ \left< \left[ \begin{array}{c} 1 \\ 2 \\ 3 \end{array} \right] , \left[ \begin{array}{c} 2 \\ 3 \\ 4 \end{array} \right] \right> $
        let v1 = [1, 2, 3]
        let v2 = [2, 3, 4]
        let c3 = zip(v1, v2).flatMap{[$0.0 + $0.1]}.reduce(0, +) // 15

        // dot product
        func dot(v1:[Int], v2:[Int])->Int{
            return zip(v1, v2).flatMap([$0.0 + $0.1]}.reduce(0, +) // 15 
        }

        
        let arr = [1, 2, 3]
        let re = arr.map{ v in return v + 1 }.reduce(1) { 
            (acc:Int, next:Int) -> Int in return acc*next
        }
        
🍑 Array and ArraySlice
        var array:Array = [1, 2, 3, 4, 5]
        
        // create a slice
        var slice:ArraySlice = [4, 5, 6, 7, 8]
        
        var sli = array[2...3]
        var startIndex = sli.startIndex
        var endIndex = sli.endIndex
        
        // convert ArraySlice to Array
        var arr = Array(slice)
        
🍑 Loop in Swift
        Apple remove C-style for loop from Swift, many developers get pissed
        We do understand the reason behind that ∵ C-style for-loop is hard to grasp and easy to make mistake.
        
        var array = [1, 2, 3]
        for item in array{
            print(item) // 1 2 3
        }

        // condition in the loop
        var done:Bool = true
        for item in array where done{
            if item == 2{
                done = false
            }else{
                print(item)
            }
        }

        for i in 0..<array.count{
            print(array[i])
        }

        for i in (0..<4){
            print("i=\(i)")
        }

        for i in (0..<4).reversed(){
            print("i=\(i)")
        }

        for i in stride(from:3, to:0, by: -1){
            print("i=\(i)") //  3 2 1 
        }

        for i in stride(from:3, through:0, by: -1){
            print("i=\(i)") // 3 2 1 0
        }

        
🍑 Swift as script language in MacOS
        1. Make sure you have swift under /usr/bin on your MacOS
        2. create file call myscript.swift, and copy the follow code to the file.
        3. Run > ./myscript.swift
        
        #!/usr/bin/swift
        func fibonacci(_ n:Int)->Int{
            if n <= 2{
                return 1
            }else{
                return fibonacci(n-2) + fibonacci(n-1)
            }
        }
        print(fibonacci(10))
        
😼 Closure and map, convert digit to String, showing the power of modulo and division
        // convert digit to String
        var digitalName = [
        0:"Zero", 1:"One", 2:"Two", 3:"Three", 4:"Four",
        5:"Five", 6:"Six", 7:"Seven", 8:"Eight", 9:"Nine"
        ]
        
        var number = [0, 1, 123]
        let strlist = number.map { (num)->String in
            var decimal = num
            var output = ""
            
            repeat {
                output = digitalName[decimal % 10]! + output  // 123 -> 3
                decimal /= 10                                 // 123 -> 12
            } while decimal > 0
            return output
        }
        print(strlist)