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 &#128054;&#128046; = "dogcow"
let `int` = 3

/* multi
/* line
*/
*/
let dog = "&#128054;"; 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()