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)












댓글 없음:

댓글 쓰기

참고: 블로그의 회원만 댓글을 작성할 수 있습니다.

5월 14일 새벽에 chatGPT 4o가 발표되었습니다. 옵티마이즈, 옴니라는 의미인데 실시간 통역, 다자간 회의, 멀티모달 기능의 강화등이 보이네요.

  초격차로 OpenAI진영이 다시 앞서가는 모양을 보여주고 있습니다. 저도 새벽에 일어나자 마자 올라온 영상들과 글을 정리하고 있습니다. ㅎㅎ 영화 HER의 사진이 새벽에 많이 올라왔었는데 저도 안본 영화입니다. 주말에 한번 봐야 할 것 같습니다....