Swift プログラミング
スキマ時間を見つけてThe Swift Programming Language を読みながら Playground で遊んでいる。
import Cocoa var str = "Hello, playground" var myVariable = 42 myVariable = 50 let myConstant = "hige" //myConstant = 3 let implicitInt = 70 let implicitDouble = 70.0 let explicitDoublt: Double = 70.0 let explicitFloat: Float = 4.0 let label = "the width is" let width = 94 let widthLabel = label + width.description + String(94) let apples = 3 let oranges = 5 let appleSummary = "I have \(apples) apples." let fruitSummary = "I have \(apples + oranges) peices of fruite" let name = "John" let height: Float = 180.0 "\(name) is \(height + 3)cm" var shoppingList = ["catfish", "water", "tulips", "blue paint"] shoppingList[1] shoppingList[1] = "hage" shoppingList var occupations = ["hige": "pon", "hage": "zou"] occupations["hige"] occupations["not found"] occupations["hige"] = "hage" occupations let emptyArray = String[]() let emptyDictionary = Dictionary<String, Float>() shoppingList = [] // type can be inferred occupations = [:] //shoppingList[0] = "apple" // this should be error. //shoppingList /* 1> var shoppingList = ["hige"] shoppingList: String[] = size=1 { [0] = "hige" } 2> shoppingList = [] 3> shoppingList $R2: String[] = size=0 4> shoppingList[0] = "apple" fatal error: Array index out of range Execution interrupted. Enter Swift code to recover and continue. Enter LLDB commands to investigate (type :help for assistance.) */ let scores = [10, 12, 3] var total = 0 for score in scores { if (score < 10) { total += score } else { total += 10 } } total /* if total { "hello" } */ var optionalString: String? = "Hello" optionalString == nil var optionalName: String? = "John" var greeting = "Hello!" if let name = optionalName { greeting = "Hello, \(name)" } optionalName = nil if let name = optionalName { greeting = "Hello, \(name)" } else { greeting = "Hello, unknown" } greeting let vegetable = "tomato" switch vegetable { case "tomato": let comment = "I like it" default: let comment = "unknown" } let map = ["hige": "pon", "john": "lennon"] for (first, second) in map { "\(first) \(second)" } var n = 2 while n < 100 { n = n * 2 } n var m = 2 do { m = m * 2 } while m < 100 m var firstForLoop = 0 for i in 0..3 { firstForLoop += 1 } firstForLoop var secondForLoop = 0 for var i = 0; i < 3; ++i { secondForLoop += 1 } secondForLoop 0..3 func greet(name :String, day: String) -> String { return "Hello \(name), today is \(day)" } greet("Bob", "Tuesday") func getGasPrices() -> (Double, Double, Double) { return (3.1, 3.2, 4.5) } getGasPrices() func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum } sumOf() sumOf(45, 50, 80) // todo: revisit this /* func averageOf(numbers: Int...) -> Int { return sumOf(numbers) / numbers.count } */ func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y } returnFifteen() func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } var increment = makeIncrementer() increment(7) let increment2 = makeIncrementer() increment2(8) func hasAnyMatches(list: Int[], condition: Int -> Bool) ->Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } hasAnyMatches([10, 11], lessThanTen) hasAnyMatches([10, 9, 11], lessThanTen) var numbers = [10, 19, 7, 12] numbers.map({ (number: Int) -> Int in return 3 * number}) numbers.map({ (number: Int) -> Int in if (number % 2 == 1) { return 0 } else { return number } }) let result = numbers.map({ number in 3 * number }) result sort([1, 10, 5], { $0 > $1}) numbers.map({ $0 * 3 }) // numbers.map({ $1 * 3 }) class Shape { var numberOfSides = 0 let name = "shape" func simpleDescription() -> String { return "\(numberOfSides) sides" } } let shape = Shape() shape.simpleDescription() shape.numberOfSides shape.name class NamedShape { var name: String // var unassigned: String init(name: String) { self.name = name; } deinit { println("deinit called") } func myname() -> String { return self.name } } NamedShape(name: "named shape").myname() class SubNamedShape: NamedShape { override func myname() -> String { return "subclass" } } SubNamedShape(name: "hige").myname() class Higepon { var firstName: String init(firstName: String) { self.firstName = firstName } var name: String { get { return "\(firstName) higepon" } set { firstName = newValue + "hage" } } } let h = Higepon(firstName: "taro") h.name h.name = "ziro" h.name = "hage" h.firstName h.name class Woman { var fakeAge: Int var age: Int { willSet { fakeAge = newValue - 5 } } init () { self.age = 35 self.fakeAge = self.age - 5 } } var w = Woman() w.age w.fakeAge w.age = 45 w.age w.fakeAge class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { // count += amount * times count += amount * times } } var c = Counter() c.incrementBy(2, numberOfTimes: 7) var myOptionalName: String? = "Taro" myOptionalName?.isEmpty myOptionalName = nil myOptionalName?.isEmpty if myOptionalName?.isEmpty { "hige" } else { "moge" } enum Rank: Int { case Ace = 1 case Two, Three case Four func simpleDescription() -> String { switch self { case .Ace: return "ace" case .Two: return "two" default: return String(self.toRaw()) } } } Rank.Ace.simpleDescription() Rank.Four.simpleDescription() Rank.fromRaw(5) struct Card { var rank: Rank func simpleDescription() -> String { return "hi I'm \(rank.simpleDescription())" } } var card = Card(rank: .Four) card.simpleDescription() enum Serverresponse { case Result(String, String) case Error(String) } let success = Serverresponse.Result("ok", "200") let failure = Serverresponse.Error("bad request") func userMessage(response: Serverresponse) -> String { switch response { case let .Result(message, statusCode):response return "yay! success \(message) \(statusCode)" case let .Error(message): return "error \(message)" } } userMessage(success) userMessage(failure) protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 4 func adjust() { simpleDescription += "adjusted" } } var simple = SimpleClass() simple.simpleDescription simple.adjust() simple.simpleDescription /* todo enum Name: ExampleProtocol { case Taro case Higepon var simpleDescription: String { return "hi" } func adjust() { println("do nothing") } } var n = Name.Higepon // todo // n.simpleDescription */ extension Int { func minusOne() -> Int { return self - 1 } } var myAge = 5 5.minusOne() func repeat<ItemType>(item: ItemType, times: Int) ->ItemType[] { var result = ItemType[]() for i in 0..times { result += item } return result } repeat("knock", 5) repeat(Rank.Ace, 4) enum OptionalValue<T> { case None case Some(T) func simpleDesc() -> String { switch self { case .None: return "None" case let .Some(value): return "Some(\(value))" } } } var possibleInteger: OptionalValue<Int> = .None possibleInteger.simpleDesc() possibleInteger = .Some(100) possibleInteger.simpleDesc() func hoge <T where T: ExampleProtocol> (value: T) -> String { return value.simpleDescription } hoge(simple) /* The Basics */ let 🐶🐮 = "dogcow" let `int` = 3 /* multi /* line */ */ let dog = "🐶"; println(dog) UInt8.min UInt8.max UInt64.max //Double.max //Float.max 3 0b11 0o03 0x03 1.25e2 000123.456 1_000_000 //let cannotBeNegative: UInt8 = -1 //let tooBig: Int8 = Int8.max + 1 let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let totatl = twoThousand + UInt16(one) let three = 3 let hog = 0.14159 let pi = Double(three) + hog typealias Hoge = UInt16 Hoge.max let i = 1 /* error if i { 3 } */ let http404Error = (404, "Not Found") let (code, message) = http404Error code message let (onlyCode, _) = http404Error onlyCode http404Error.0 http404Error.1 let http200Status = (code: 200, desc: "ok") http200Status.code http200Status.desc let possibleNumber = "123" let convertedNumber = possibleNumber.toInt() if convertedNumber { "\(convertedNumber!)" } if let number = possibleNumber.toInt() { number } var surveyAnswer: String? surveyAnswer let possibleString: String? = "hage" possibleString! let assumedString: String! = "hige" assumedString let age = -3 //assert(age >= 0) let x: UInt8 = 255 let y: UInt8 = 1 //x + y x &+ y let c1: Character = "r" let c2: Character = "y" c1 + c2 1...5 1..5 "".isEmpty String().isEmpty var greeting2 = "hell" func stringIsValueType(msg: String) { println(msg) } stringIsValueType(greeting2) greeting2 countElements(greeting2) "hello" == "hello" "hello".hasPrefix("he") var a = Array<String>() a = String[]() a.append("hige") a a += ["hage", "moge", "ramen"] a a[0...1] = ["new"] a a.insert("Maple", atIndex: 1) for (index, value) in enumerate(a) { println("[\(index)] = \(value)") } var dic = ["one": 1, "two": 2] dic dic["three"] = 3 dic dic["three"] = 3333 dic let ret = dic.updateValue(5, forKey:"five") ret if ret { "already there" } else { "new" } switch 1 { case 1: println("1") fallthrough default: println("default") } ret func hogeFunc(extX x: Int, extY y: Int) -> Int { return x + y } hogeFunc(extX: 3, extY: 4) //hogeFunc(extY: 3, extX: 4) func higeFunc(#x: Int, #y: Int) -> Int { return x + y } higeFunc(x: 2, y: 3) func hageFunc(x: Int = 5) -> Int { return x } hageFunc() hageFunc(x: 4) func hageFunc2(x: Int = 4, #y: Int) -> Int { return x + y } hageFunc2(y: 5) func swapTwoInts(inout a: Int, inout b: Int) { let temp = a; a = b b = temp } var aa = 1 var bb = 2 swapTwoInts(&aa, &bb) 3 aa bb //Void var myFunc: ((Int, Int) -> Int)? if let val = myFunc { "some" } else { "empty" } func addSeven(x: Int, y: Int, adder: (Int, Int) -> Int) -> Int { return adder(x, y) + 7 } addSeven(1, 3, { return $0 + $1 }) func face(isSad: Bool) -> (greeting: String) -> String { if isSad { return { (greeting) in return ":( \(greeting)" } } else { return { (greeting) in return ":) \(greeting)" } } } face(true)(greeting: "I'm sorry") face(false)(greeting: "Happy") func face2(isSad: Bool) -> (greeting: String) -> String { if isSad { return { ":( \($0)" } } else { return { ":) \($0)" } } } face2(true)(greeting: "I'm sorry") let names = ["john", "paul", "george"] sort(names, { $0 > $1 }) sort(names, >) sort(names) { $0 > $1 } names func makeCounter() -> () -> Int { var counter = 0 return { ++counter } } let counter = makeCounter() counter() counter() let counter2 = makeCounter() counter2() enum Language: String { case English = "English" case Japanese = "日本語" } Language.English.toRaw() class Taro { let name = "Taro" let modelNo: String init(modelNo: String) { self.modelNo = modelNo } } let taro = Taro(modelNo: "initial") taro.name taro.modelNo let refTaro: Taro = taro let anotherTaro = Taro(modelNo: "initial") taro === taro taro === refTaro taro === anotherTaro //taro == anotherTaro var numbersDic = ["one": 1, "two": 2] func addNumber(var dic: Dictionary<String, Int>, key: String, value: Int) { dic[key] = value } // the dic is copied addNumber(numbersDic, "three", 3) numbersDic var a1 = [1, 2, 3] let b1 = a1 a1[0] b1[0] a1[0] = 99 a1 b1 a1.append(4) a1 b1 a1.unshare() a1 === b1 a1[0...1] === b1[0...1] a1.copy() func computeHeavyName() -> String { var ret = "" for i in 0...5 { ret += String(i) } println("Hello") return ret } class Ziro { @lazy var heavyName: String = computeHeavyName() var greeting: String { get { return "Hello, I'm " + heavyName } } // not supported yet // class let name = "ziro" // class func hoge { // println("hoge") // } var beatles = ["John", "Paul", "George", "Ringo"] subscript(index: Int) -> String { get { return beatles[index] } set(newValue) { beatles[index] = newValue } } } let ziro = Ziro() ziro.greeting ziro.heavyName ziro[1] class BaseTaro { var name: String init(name: String) { self.name = name } } var baseTaro = BaseTaro(name: "base taro") class SmartTaro: BaseTaro { let nickName: String func greeting() { println("Hello, I'm Smart taro \(name)") } func onePlusOne() -> Int { return 2 } init(nickName: String, name: String) { self.nickName = nickName super.init(name:name) } } var smartTaro = SmartTaro(nickName:"smart boy", name: "smart taro") smartTaro.greeting() smartTaro.onePlusOne() class FunnyTaro: SmartTaro { @final override func greeting() { println("Poo!") } override func onePlusOne() -> Int { return super.onePlusOne() + 1 } } var funnyTaro = FunnyTaro(nickName:"funny boy", name: "funny taro") funnyTaro.greeting() funnyTaro.onePlusOne() class Person { let name: String var ssn: String? init(fromString name: String) { self.name = name if (self.name == "hige") { ssn = "hige" } } init(fromNumber name: Int) { self.name = String(name) } } Person(fromString: "taro") var person = Person(fromNumber: 4649) person.ssn person = Person(fromString: "hige") person.ssn class Saburo { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[unknown]") } } Saburo() Saburo(name: "sabu-chan") class SmartSaburo: Saburo { let isSuper: Bool let hoge: String = { return "hoge" }() init(name: String, isSuper: Bool) { self.isSuper = isSuper super.init(name: name) } convenience init(name: String) { self.init(name: name, isSuper: false) } } SmartSaburo(name: "smart saburo") SmartSaburo(name: "smart saburo-x", isSuper: true) class Empty { deinit { println("deinit called") } } var ref1: Empty? = Empty() var ref2: Empty? = ref1 ref1 = nil ref2 = nil class IDCard { weak var owner: Man? init() { println("IDCar init") } deinit { println("IDCard deinit") } } class Man { let name: String var idCard: IDCard? init(name: String) { println("Man init") self.name = name } deinit { println("man deinit") } } var testMan: Man? = Man(name: "test") testMan = nil var man: Man? man = Man(name: "taro") var idCard: IDCard? idCard = IDCard() idCard!.owner = man man!.idCard = idCard // Unfortuanatly deinit is rarely called in playground man = nil idCard = nil println("how?") // weak: both of which are allowed to be nil // unowned: one can be nil, the other can not be nil // Strong reference cycle class Human { let firstName: String let lastName: String init(firstName: String, lastName: String) { println("\(firstName) init") self.firstName = firstName self.lastName = lastName } @lazy var fullName: () -> String = { [unowned self] in return "\(self.firstName) \(self.lastName)" } deinit { println("\(firstName) deinit") } } var human: Human? human = Human(firstName: "Taro", lastName: "Minowa") //human is Human human = nil class Z { } class ZZ: Z { let name = "zz" } var z: Z? = Z() if z is Z { "Z!" } var zz: ZZ? = ZZ() if zz is ZZ { "ZZ!" } z = zz let realZZ: ZZ = z as ZZ realZZ.name let someObjects: AnyObject[] = [3, "hige"] let stringObjects: AnyObject[] = ["hige", "hage"] for s in stringObjects as String[] { println(s) } class TestNested { enum Hige { case Pon case Kun } } TestNested.Hige.Pon class Ponkotsu { var name: String init(name: String) { self.name = name } } var ponkotsu = Ponkotsu(name: "taro") ponkotsu.name /* Crash extension Ponkotsu { var greeting: String { return "Hello I'm \(name)" } } ponkotsu.greeting */ extension Ponkotsu { convenience init(myNumber: Int) { self.init(name: String(myNumber)) } } var ponkotsu2 = Ponkotsu(myNumber:3) extension Ponkotsu { func greeting() { println("Hi I'm \(name)") } } ponkotsu2.greeting() extension Ponkotsu { func changeFunnyName(name: String) { self.name = "hoge \(name)" } } ponkotsu2.changeFunnyName("taro") /* extension Ponkotsu { subscript(index: Int) -> Character { return "a" } } ponkotsu2[2] */ class Ichiro { } class Ziro { } class Saburo { } @infix func + (left: Ichiro, right: Ziro) -> Saburo { return Saburo() } Ichiro() + Ziro()