2014년 12월 23일 화요일

애플의 새로운 개발언어 Swift - 함수#10

// Playground - noun: a place where people can play

import UIKit

func doSomething() {
    println("기본적인 함수의 형태")
}

//함수 호출
doSomething()

//리턴값이 있는 함수
func doSomething2() -> String {
    return "something fun to do on Swift"
}

doSomething2()

//변수 파라메터 
func square(var num: Int) -> Int {
    return num*num
}

square(2)

//파라메터가 2 이상인 경우
func add(a:Int, b:Int) -> Int {
    return a+b
}

add(1, 2)

//튜플을 리턴
//가독성을 위해 튜플의 이름을 지정하는 습관을 가지는 것이 좋다
func fetchName(id:Int) -> (statusCode:Int, name:String) {
    var code = 200
    var fetchedName = "James"
    return (code, fetchedName)
}

var result = fetchName(123)
println(result.statusCode)
println(result.name)

//옵셔널 튜플을 리턴하는 경우 
//(statusCode:Int, name:String)? 이렇게 표기하면 nil 리턴될 있다
//그러나 (Int?, String?) 같이 선언된 튜플은 개별 요소가 nil 있지만 
//튜플 전체가 nil 없다.
func fetchName2(id:Int) -> (statusCode:Int, name:String)? {
    if id <= 0 {
        return nil
    }
    
    var code = 200
    var fetchedName = "James"
    
    return (code, fetchedName)
}

if let result = fetchName2(123) {
    println(result.statusCode)
    println(result.name)
}

// Playground - noun: a place where people can play

import UIKit

//두개의 값을 교환하는 함수
//정상적으로 처리되지 않는다
func swapNumbers(var a:Int, var b:Int) {
    let tmp = a;
    a = b;
    b = tmp;
}

var foo = 10
var bar = 20

swapNumbers(foo,bar)

println(foo)
println(bar)

//이번에는 입출력 파라메터로 구현해 본다.
//입출력 파라메터는 몇가지 제약을 가지고 있다. 입출력 파라메터는 기본값을 가질 없고
//가변인자 파라메터를 입출력 파라메터로 선언할 없다
//그리고 inout, var, let 파라메터 선언시 서로 베타적이기 때문에 동시에 사용할
//없다.
func swapNumbers2(inout a:Int, inout b:Int) {
    let tmp = a;
    a = b;
    b = tmp;
}

var foo2 = 10
var bar2 = 20
swapNumbers2(&foo, &bar)
println(foo)
println(bar)

//함수 형식을 사용한 계산기 
//닷넷의 델리게이트와 같은 개념(Function Type-함수 형식)
//C언어의 함수 포인터와 동일하다.
//1)우선 사칙 연산을 위한 4개의 함수를 정의한다. 비슷한 모양이다.
func add(a:Int, b:Int) -> Int {
    return a+b
}
func subtract(a:Int, b:Int) -> Int {
    return a-b
}
func multiply(a:Int, b:Int) -> Int {
    return a*b
}
func divide(a:Int, b:Int) -> Int {
    return a/b
}

//2)어떤 함수들인지 형태를 지정한다.
var f:((Int, Int) -> Int)? = nil
var op = "+"
switch op {
    case "+":
        f = add
    case "-":
        f = subtract
    case "*":
        f = multiply
    case "/":
        f = divide
    default:
        break
}
//3)아래와 같이 호출한다.
if f != nil {
    var result = f!(2,3)
    println("2 \(op) 3 = \(result)")
}

//함수 형식을 파라메터로 전달
func processResult(function:(Int, Int) -> Int, a:Int, b:Int) {
    println("Result: \(function(a,b))")
}

var f2:((Int, Int) -> Int)? = nil
var op2 = "*"
switch op2 {
case "+":
    f2 = add
case "-":
    f2 = subtract
case "*":
    f2 = multiply
case "/":
    f2 = divide
default:
    break
}

if f2 != nil {
    processResult(f2!, 20, 3)
}

//함수 형식을 리턴하는 함수 
//함수 선언에 포함된 첫번째 리턴 화살표는 항상 함수의 파라메터와 리턴형을 구분하는 역할을 한다.
func select(op:String) -> ((Int, Int) -> Int)? {
    switch op {
        case "+":
            return add
        case "-":
            return subtract
        case "*":
            return multiply
        case "/":
            return divide
        default:
            return nil
    }
}

var op3 = "+"
var f3:((Int,Int) -> Int)? = select(op3)

if f != nil {
    processResult(f3!, 2, 3)
}


// Playground - noun: a place where people can play

import UIKit

//내포된 함수(Nested Function)
//앞에서 살펴본 함수는 전역 공간에 선언된 전역 함수들이다
//전역 함수는 코드의 가독성이 떨어지고 객체지향의 특징인 은닉을 만족시키지 못한다
//코드의 규모가 커지면 커플링이 심해지고 쓰레드의 안정성이 떨어질 있다
//아래와 같이 내포된 함수(add, subtract, multiply, divide) 기본적으로
//select함수 내부에서만 인식되고 호출될 있다
//하지만 select함수와 같이 함수형을 리턴하는 경우에는 호출자가 포함된 공간으로
//사용 범위가 확대된다.
func select(op: String) -> ((Int, Int) -> Int)? {
    func add(a:Int, b:Int) -> Int {
        return a+b
    }
    func subtract(a:Int, b:Int) -> Int {
        return a+b
    }
    func multiply(a:Int, b:Int) -> Int {
        return a+b
    }
    func divide(a:Int, b:Int) -> Int {
        return a+b
    }
    
    switch op {
        case "+":
            return add
        case "-":
            return subtract
        case "*":
            return multiply
        case "/":
            return divide
        default:
            return nil
    }
}

var op = "+"
var f:((Int, Int) -> Int)? = select(op)

if f != nil {
    println("Result: \(f!(2,3))")
}

//커링 함수: 커링(Currying) 여러개의 파라메터를 가진 함수를 하나의 파라메터를 가진 여러 함수로 분리하는
//프로그래밍 기법이다. 실행에 따라 변경되는 일부 파라메터를 나중에 전달할 있어 함수를 객체처럼 추상화 있다
// 기법의 명칭은 수학자인 헤스켈 커리의 이름에서 유래했다
//커리드 함수는 하나의 파라메터를 전달받아 함수를 리턴한다. 리턴된 함수는 커리드 함수 체인에 있는
//다음 파라메터를 전달받고 다른 함수를 리턴한다
func add(a:Int, b:Int) -> Int {
    return a+b
}
func addCurried(a:Int) -> (Int -> Int) {
    func addInternal(b:Int) -> Int {
        return a+b
    }
    return addInternal
}
var result = addCurried(1)(2)
println(result)












2014년 12월 22일 월요일

애플의 새로운 개발언어 Swift - 반복문과 제어문 #9

// Playground - noun: a place where people can play

import UIKit

//for문에서 {} 생략할 없는 것에 주의한다.
var str = "Swift"
for ch in str  {
    println(ch)
}

var total = 0
var num = 1

while num <= 100 {
    total += num++
}

println("total: \(total)")

//if문에서 조건식을 감싸는 괄호는 제거되었고 {} 반드시 있어야 한다
var password = "1234abcde"
var specialCharSet = NSCharacterSet.symbolCharacterSet()

if countElements(password)<8 {
    println("password too short")
}
else if password.rangeOfCharacterFromSet(specialCharSet) == nil {
    println("password must have symbol char")
}
else {
    print("password is valid")
}

import Foundation
//switch Swift에서 break 사용하지 않는다
//Objective-C에서는 정수만 비교 가능했지만 지금은 정수, Double, String 가능하다.
var textAlignment = NSTextAlignment.Center

switch textAlignment {
case NSTextAlignment.Left:
     println("left")
case NSTextAlignment.Center:
     println("center")
case NSTextAlignment.Right:
     println("right")
default:
     println("default")
}

//Objective-C 폴쓰루를 지원한다
//비슷하게 Swift에서 구현하려면 아래와 같이 한다
var textAlignment2 = NSTextAlignment.Left

switch textAlignment2 {
case NSTextAlignment.Left:
    println("left")
    fallthrough
case NSTextAlignment.Center:
    println("center")
    fallthrough
case NSTextAlignment.Right:
    println("right")
    fallthrough
default:
    println("default")
}

//문자열 매칭 
//switch구문에서 대소문자를 구분하는 것에 주의한다.
var vendor = "apple"
switch vendor {
    case "APPLE":
        println("iMac")
    case "apple":
        println("iPhone")
    case "google":
        println("Android")
    case "ms":
        println("Windows Phone")
    default:
        println("others...")
}

//튜플 매칭
// _ 사용하면 특정 요소를 패턴 매칭에서 제외할 있다.
var diff = (0, 32)

switch diff {
case (0,0):
    println("no move")
case (_,0):
    println("move horizontally")
case (0,_):
    println("move vertically")
default:
    println("outside screen")
}

// 바인딩을 사용하는 경우
//_문자는 튜플의 특정 요소를 무시하기 때문에 케이스 구문 내부에서 사용하려면
//임시 상수로 대치할 있다
//임시 상수로 대체된 요소는 패턴 매칭에서 제외되지만 요소가 가진 
//값은 임시 상수에 할당되므로 case 내부에서 사용할 있다
//이러한 방식을 바인딩(value binding)이라고 한다.
var diff2 = (30, 0)
switch diff2 {
case (0,0):
    println("no move")
case (let x, 0):
    println("move horizontally: \(x)px")
case (0, var y):
    println("move vertically: \(y)px")
default:
    println("move diagonally")
}

// 바인딩 시에는 default 생략할 있다. 원래는 안되지만 
//이유는 switch 마지막 부분에 바인딩을 통해 앞에서 일치하지 않는 
//모든 패턴을 매칭시킬 있는 case 제공하기 때문이다
var diff3 = (30, 20)
switch diff3 {
case (0,0):
    println("no move")
case (let x, 0):
    println("move horizontally: \(x)px")
case (0, let y):
    println("move vertically: \(y)px")
case (let x, let y):
    println("move \(x)x\(y)")
}

//왼쪽과 오른쪽 방향 구분 
var diff4 = (30, 0)
switch diff4 {
case (0,0):
    println("no move")
case (let x, 0):
    if x<0 {
        println("move left: \(x)px")
    } else {
        println("move right: \(x)px")
    }
case (0, let y):
    println("move vertically: \(y)px")
default:
    println("move diagonally")
}

//조건을 상세하게 지정하는 where 
var diff5 = (30, 0)
switch diff4 {
case (0,0) where diff5.0 < 0:
    println("no move")
case (let x, 0) where x < 0:
    println("move left: \(x)px")
case (let x, 0) where x > 0:
    println("move right: \(x)px")
default:
    println("move diagonally")
}

//새로 도입된 범위 연산자를 사용하는 경우 
var count = 50
switch count {
case 1..<10:
    println("small box")
case 10...30:
    println("medium box")
case 31...100:
    println("big box")
default:
    println("not available")
}

//중첩된 for 반복문 
for outerNum in 1...10 {
    for innerNum in 1...10 {
        if innerNum > 5 {
            break
        }
        println("inner: \(innerNum)")
    }
    println("outer: \(outerNum)")
}

//라벨을 붙여서 사용하는 경우
//바깥쪽 라벨을 지정해서 탈출하기 때문에 5번만 반복하고 종료된다.
OUTER_LOOP: for outerNum in 1...10 {
    INNER_LOOP: for innerNum in 1...10 {
        if innerNum > 5 {
            println("END OUTER")
            break OUTER_LOOP
        }
        println("inner: \(innerNum)")
    }
    println("OUTER: \(outerNum)")
}


'일론 머스크' '젠슨 황' AI 리더들, 그들의 성공 비결은 바로 이것 - 누가 부자가 되는가 영상입니다. ㅎㅎ

  책을 통해서만 접했던 내용들을 영상으로 보니 더 실감이 납니다. KBS에서 방송된 내용인데 주말에 보시면 좋은 영상입니다. 엔비디아의 주가가 이해가 됩니다. ㅋㅋ 생각보다 미국시장이 강한 것이 AI는 거의 미국과 중국이 주도하는 시장이 되고 있습...