클로저 - @autoclosure
파라미터로 전달된 일반 구문 또는 함수를 클로저로 래핑(Wrapping) 한다는 의미이다.
즉, @autoclosure가 붙은 경우에는 일반 구문을 인자값으로 넣어도 컴파일러가 알아서 클로저로 만들어준다.
아래 코드는 클로저가 어떻게 판단을 지연하는지 보여준다.
클로저 내부의 코드에 의해 fruits 배열의 첫 번째 요소는 삭제 되지만,
클로저가 실제로 호출되기 전까지 삭제되지 않습니다.
var fruits: [String] = ["Apple", "Banana", "Kiwi", "Melon"]
let fruitsCheck = { fruits.removeFirst()}
print(fruits.count) // 4
print("삭제 아이템: \(fruitsCheck())") // 삭제 아이템: Apple
print(type(of: fruitsCheck)) // () -> String
print(fruits.count) // 3
클로저는 선언 단계에서 바로 실행되지 않는다.
호출이 되어야만 실행이 된다.
fruitsCheck 타입은 String이 아니고 파라미터가 없고, 문자열을 반환하는 () -> String 이다.
함수의 인수로 클로저를 전달하면 위와 같은 지연 판단과 동일한 동작을 할 수 있다.
func runFunction(fruitsCheck: () -> String) {
print("삭제 아이템: \(fruitsCheck())")
}
runFunction(fruitsCheck: { fruits.removeFirst()})
print(fruits.count)
runFunction(fruitsCheck:) 함수는 fruits 배열의 제거할 첫 번째 아이템을 반환한다.
아래에서 runFunction() 함수는 파라미터 타입에 "@autoclosure" 속성을 표기하여 자동 클로저를 가진다.
var fruits: [String] = ["Apple", "Banana", "Kiwi", "Melon"]
print(fruits.count) // 4
func runFunction(fruitsCheck: @autoclosure() -> String) {
print("삭제 아이템: \(fruitsCheck())")
}
runFunction(fruitsCheck: fruits.removeFirst()) // 삭제 아이템: Apple
print(fruits.count) // 3
이제 클로저 대신 String 타입의 인수를 받는 것 처럼 함수를 호출 할 수 있다.
// String 타입의 인수를 받는 것도 가능
runFunction(fruitsCheck: "사과") // 삭제 아이템: 사과
⭐️ 클로저가 호출될 때까지 코드 내부 실행이 되지 않기 때문에 자동 클로저는 판단을 지연할 수 있다.
⭐️ 인자값을 클로저 형태로 넣어줄 필요가 없기 때문에 "{ }" 형태가 아닌 "( )" 형태로 사용할 수 있다.
⭐️ 너무 남발해서 사용하진 말자... 아직은 잘 모르겠다..