🐼 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)