[Swift 문법] 클로저

!·2022년 6월 25일
0

Swift 문법

목록 보기
14/27

클로저

  • 코드의 블록이다.
  • 일급 시민으로써 변수, 성수 등으로 저장이 가능하며, 전달인자로 전달이 가능하다.
  • 함수는 이름이 있는 클로저이다.
{ (매개변수 목록) -> 반환타입 in
	함수 구현부
}
func sumFunction(a: Int, b: Int) -> Int{
	return a+b
}

var sum : (Int, Int) -> Int = {(a : Int, b : Int) -> Int in
	return a+b
}

let sumResult: Int = sum(1,2)
print(sumResult) // 3

sumResult = sumFuncion(a:b:)
print(sumResult) // 3

함수 전달인자로서의 클로저

  • 클로저는 주로 함수의 전달인자로 많이 사용된다.
  • 함수 내부에서 원하는 코드블럭을 실행할 수 있다.
let add : (Int, Int) -> Int
add = { (a:Int, b:Int) -> Int in
	return a+b
}

let substract : (Int, Int) -> Int
sunstract { (a:Int, b:Int) -> Int in
	return a-b
}

let divide : (Int, Int ) -> Int
devide = {(Int, Int) -> Int in 
	return a / b
}

func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int { 
	return method(a,b)
}

var calculated : Int 

calculated = calculate(a: 10, b:10, method: add)
print(calculated) // 20

calculated = calculate(a: 10, b: 10, method: substract)
print(calculated) // 0

calculated = calculate(a: 10, b: 10, method: divide)
print(calculted) // 1

calculated = calculate(a: 10, b: 10, method: {(left: Int, right: Int) -> Int in result left * right
} // 코드 블록을 바로 작성해서 넘겨줄 수 있다는 장점이 있다

후행 클로저

  • 클로저함수의 마지막 전달인자라면 마지막 매개변수 이름을 생략한 후 함수 소괄호 외부에 클로저를 구현할 수 있다.
  • 또한, 클로저로 전달되는 인자가 하나라면 () 를 생략할 수도 있다.
result = calculate(a: 10, b:10){(left: Int, right: Int) -> Int in
	return left * right
}
hello = printHello{print("hello")}

print(result) // 100

반환타입 생략

  • calculate() 함수의 정의부에서 전달인자의 method() 함수는 반환형이 Int이다. 따라서 만약 method()클로저로 전달한다면 반환형은 생략이 가능하다.
  • in 키워드는 생략할 수 없다.
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) in
    return left + right
})

print(result) // 20

// 후행클로저와 함께 사용할 수도 있습니다
result = calculate(a: 10, b: 10) { (left: Int, right: Int) in
    return left + right
}

print(result) // 20

타입 유추

  • 메서드에 전달인자로 전달되는 클로저는 메소드에서 요구하는 형태로 전달해야 한다.
  • 이는 전달인자로 전달한 클로저는 이미 타입을 준수하고 있다고 말할 수 있기떄문에 이를 생략할 수 있다.
result = calculate(a: 10, b: 10){(left, right) in return left + right}

단축 인자이름

  • 클로저매개변수 이름이 굳이 불필요하다면, 단축 인자이름을 활용할 수 있다. $0, $1, $2로 표현한다.
  • 이때는 in 키워드를 생략할 수 있다.
result = calculate(a: 10, b: 10, method: {
    return $0 + $1
})

print(result) // 20


// 당연히 후행 클로저와 함께 사용할 수 있습니다
result = calculate(a: 10, b: 10) {
    return $0 + $1
}

print(result) // 20

암시적 반환 표현

  • 클로적가 반환하는 값이 있다면 클로저의 마지막 줄의 결과값은 암시적으로 반환값으로 취급된다.
result = calculate(a: 10, b: 10) {
    $0 + $1
}

print(result) // 20

// 간결하게 한 줄로 표현해 줄 수도 있습니다
result = calculate(a: 10, b: 10) { $0 + $1 }

print(result) // 20

축약 전과 후 비교

//축약 전
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

//축약 후
result = calculate(a: 10, b: 10) { $0 + $1 }

print(result) // 20

값 획득

  • 클로저는 자신이 정의된 위치의 주변 문맥을 통해 상수나 변수를 획득할 수 있습니다.
  • 값 획득을 통해 클로저는 주변 상수나 변수가 존재하지 않을 때도 해당 상수나 변수의 값을 자신 내부에서 참조하거나 변경할 수 있다.
func makeIncrementer(forIncrementer amount: Int) -> (() -> Int) {
	var runningTotal = 0
    func incrementer() -> Int{
    	runningTotal += amount
       	return runningTotal
    }
    return incrementer
}
  • 이때 runningTotal과 amount 변수는 makeIncrementer 함수의 실행이 끝나도 사라지지 않는다.
  • 게다가 incrementer 함수가 호출될 때마다 사용할 수 있다.
let incrementByTwo: (() -> Int) = makeIncrementer(forIncrement: 2)

let first: Int = incrementByTwo() // 2
let second: Int = incrementByTwo() // 4
let third: Int = incrementByTwo() // 6
  • 이때, makeIncrementer 함수를 하나 더 생성해주면, 자신만의 runningTotal 변수와 amount 변수를 갖는다.
profile
개발자 지망생

0개의 댓글