@autoclosure
파라미터로 전달된 일반 구문 & 함수를 클로저로 래핑(Wrapping)하는 것을 말함
"@autoclosure" 라는 키워드를 파라미터 함수 타입 앞에 사용
func runFunction(closure: @autoclosure ()->()) {
// 내부코드
}
여기서 closure 라는 파라미터는
실제로 클로저를 받지 않았지만, 클로저처럼 사용 가능
※ 단, 실제 클로저를 전달받지 않았기 때문에
파라미터로 값을 넘기는 것 처럼 ( ) 를 통해 구문을 넘기는게 가능
runFunction(closure: 22>=23)
" 22>=23" 은 일반 구문이지만, 실제로는
@autoclosure로 설정했기 때문에 클로저처럼 사용 가능
@autoclosure는 클로저가 호출되기 전까지 클로저 내부의 코드가 동작하지 않음
즉, 지연 연산이 가능함
이를 통해 연산에 자원을 많이 소모되는 부작용이 우려될 때 유용하게 사용 가능
아래 코드를 통해 클로저가 연산을 어떻게 지연시키는지 알 수 있음
var customersInLine: [String] = ["jerry", "mike", "tom", "marry"]
print(customersInLine.count) // 4
// 클로저를 이용, 클로저 내부의 코드를 미리 실행하지 않고, 가지고만 있음
let customerProvider: () -> String = {
return customersInLine.removeFirst()
}
print(customersInLine.count) // 4
customerProvider 상수에 저장해둔 클로저는
바로 아래 customerInLine.count 구문을 실행해도
클로저 내부의 연산은 방영되지 않음
// 실제로 실행
print("Now serving \(customerProvider())!") // Now serving jerry!
print(customersInLine.count) // 3
customerProvider 라는 클로저를 실행해야 연산 진행
따라서 클로저를 실행하지 않는다면? 연산은 진행되지 않음
같은 조건의 클로저를 함수의 전달인자로 전달한다면?
var customersInLine: [String] = ["jerry", "mike", "tom", "marry"]
print(customersInLine.count) // 4
func serveCustomer(_ customerProvider:() -> String) {
print("Now serving \(customerProvider())!")
}
serveCustomer( { customersInLine.removeFirst() }) // Now serving jerry!
위의 코드를 다시 자동 클로저를 사용한다면?
var customersInLine: [String] = ["jerry", "mike", "tom", "marry"]
print(customersInLine.count) // 4
func serveCustomer(_ customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serveCustomer(customersInLine.removeFirst()) // Now serving jerry!
@autoclosure 라는 속성을 부여한 매개변수는 클로저 대신에
serveCustomer( { customersInLine.removeFirst() })
customersInLine.removeFirst() 코드의 실행 결과인 String 타입의 문자열을
전달인자로 받게 됨
serveCustomer(customersInLine.removeFirst())
여기서 String 타입의 값을 전달 받는 이유는
자동 클로저의 반환 타입이 ( ) -> String 이기 때문
자동 클로저는 전달인자를 갖고 있지 않기 때문에
반환 타입의 값이 자동 클로저의 매개변수로 전달되면
이를 클로저로 자동으로 변환해줌