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