Swift @autoclosure 사용방법
나는 글을 쓸 때 알아차렸다.assertSwift에서는 첫 번째 값이 다음과 같이 입력됩니다.
@autoclosure() -> Bool
일반적인 것을 반환하기 위해 과부하된 메서드를 사용하여T값을 사용하여 존재 여부를 테스트합니다.LogicValue protocol.
하지만 엄밀하게 당면한 문제에 집착하고 있다.필요한 것 같습니다.@autoclosure그러면 a가 반환됩니다.Bool.
파라미터를 사용하지 않고 Bool을 반환하는 실제 클로저를 쓰는 것은 작동하지 않습니다. 클로저를 호출하여 다음과 같이 컴파일합니다.
assert({() -> Bool in return false}(), "No user has been set", file: __FILE__, line: __LINE__)
그러나 Bool을 통과하면 다음과 같이 됩니다.
assert(false, "No user has been set", file: __FILE__, line: __LINE__)
그래서 무슨 일이야?뭐가@autoclosure?
편집: @auto_closure이름이 변경되었습니다.@autoclosure
하나의 인수를 사용하는 함수, 즉 인수를 사용하지 않는 단순한 닫힘을 고려합니다.
func f(pred: () -> Bool) {
if pred() {
print("It's true")
}
}
이 함수를 호출하려면 폐쇄를 통과해야 합니다.
f(pred: {2 > 1})
// "It's true"
중괄호를 생략하면 식이 전달되고 오류가 발생합니다.
f(pred: 2 > 1)
// error: '>' produces 'Bool', not the expected contextual result type '() -> Bool'
@autoclosure식 주위에 자동 닫힘을 만듭니다.그래서 발신자가 다음과 같은 표현을 쓸 때2 > 1자동으로 클로저로 포장되어,{2 > 1}전달되기 전에f이걸 함수에 적용하면f:
func f(pred: @autoclosure () -> Bool) {
if pred() {
print("It's true")
}
}
f(pred: 2 > 1)
// It's true
그래서 마무리로 포장할 필요 없이 표현만으로 동작합니다.
여기 실용적인 예가 있습니다.print오버라이드(Swift 3) :
func print(_ item: @autoclosure () -> Any, separator: String = " ", terminator: String = "\n") {
#if DEBUG
Swift.print(item(), separator:separator, terminator: terminator)
#endif
}
당신이 말할 때print(myExpensiveFunction()),나의print오버라이드(override)는 스위프트의 것을 무색하게 한다.print라고 불리고 있습니다. myExpensiveFunction()따라서 폐쇄로 감싸지고 평가되지 않습니다.Release 모드일 경우 평가되지 않습니다.item()호출되지 않습니다.이렇게 해서 Version이 있습니다.print릴리스 모드에서는 인수를 평가하지 않습니다.
문서에서 auto_closure에 대한 설명:
auto_closure Atribute는 파라미터 타입이 ()이고 식 타입을 반환하는 함수유형에 적용할 수 있습니다(Type Attributes 참조).자동 노출 함수는 식 자체 대신 지정된 식에 대한 암묵적 닫힘을 캡처합니다.다음 예제에서는 auto_closure 속성을 사용하여 매우 단순한 아사트 함수를 정의합니다.
그리고 여기 애플이 그것과 함께 사용하는 예가 있다.
func simpleAssert(condition: @auto_closure () -> Bool, message: String) {
if !condition() {
println(message)
}
}
let testNumber = 5
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
기본적으로 부울식을 닫는 대신 첫 번째 인수로 전달하면 자동으로 닫힘이 생성됩니다.따라서 메서드는 부울식이지만 닫힘을 전달할 수 없기 때문에 false를 메서드에 전달할 수 있습니다.
은 유용한 입니다.@autoclosure https://airspeedvelocity.net/2014/06/28/extending-the-swift-language-is-cool-but-be-careful/httpsairspeedvelocity.net/2014/06/28//
이제 까지 첫 번째 매개 변수로 전달된 조건부 식은 자동으로 닫힘 식으로 정리되어 루프 주위를 돌 때마다 호출할 수 있습니다.
func until<L: LogicValue>(pred: @auto_closure ()->L, block: ()->()) {
while !pred() {
block()
}
}
// doSomething until condition becomes true
until(condition) {
doSomething()
}
이것은 클로즈 콜에서 컬리브레이스를 제거하는 단순한 방법입니다.
let nonAutoClosure = { (arg1: () -> Bool) -> Void in }
let non = nonAutoClosure( { 2 > 1} )
let autoClosure = { (arg1: @autoclosure () -> Bool) -> Void in }
var auto = autoClosure( 2 > 1 ) // notice curly braces omitted
@loclosure(공개)
@autoclosure는 내부 변환합니다.closure [대략]
장점:
-
assert(2 == 5, "failed") - 중괄호는 사용되지 않습니다.
단점
- 읽기 어렵다.함수를 내부로 전달했을 때
@autoclosure이 함수가 지연될지는 명확하지 않습니다(내부 폐쇄이기 때문입니다).fooWithAutoClosure(a: foo0())-foo0()되지 않습니다.
고압 인클로저를 과도하게 사용하면 코드를 이해하기 어려울 수 있습니다.컨텍스트와 기능명은 평가가 연기되고 있음을 명확히 해야 한다.
@autoclosure변수를 하지 않습니다.func foo(p: @autoclosure () -> Void)@autoclosure적절한 반환 유형만 있는 함수를 받아들인다.
기타 예
//functions block
func foo0() -> String {
return "foo0"
}
func foo1(i1: Int) -> String {
return "foo1 " + String(i1)
}
func foo2(i1: Int, i2: Int) -> String {
return "foo2 " + String(i1 + i2)
}
//closures block
func fooWithClosure0(p: () -> String) -> String {
return "fooWithClosure0 " + p()
}
func fooWithClosure1(p: (Int) -> String) -> String {
return "fooWithClosure1 " + p(1)
}
func fooWithClosure2(p: (Int, Int) -> String) -> String {
return "fooWithClosure2 " + p(1, 2)
}
//@autoclosure
func fooWithAutoClosure(a: @autoclosure () -> String) -> String {
return "fooWithAutoClosure " + a()
}
//test closures
func testClosures() {
XCTAssertEqual("fooWithClosure0 foo0", fooWithClosure0(p: foo0))
XCTAssertEqual("fooWithClosure1 foo1 1", fooWithClosure1(p: foo1))
XCTAssertEqual("fooWithClosure2 foo2 3", fooWithClosure2(p: foo2))
XCTAssertEqual("fooWithClosure2 foo2 3", fooWithClosure2(p: { (i1, i2) -> String in
return "fooWithClosure2 " + "foo2 " + String(i1 + i2)
}))
}
//test @autoclosure
func testAutoClosures() {
XCTAssertEqual("fooWithAutoClosure HelloWorld", fooWithAutoClosure(a: "HelloWorld")) //"HelloWorld" is String as returned value of @autoclosure
XCTAssertEqual("fooWithAutoClosure foo0", fooWithAutoClosure(a: foo0()))
XCTAssertEqual("fooWithAutoClosure foo1 1", fooWithAutoClosure(a: foo1(i1: 1)))
XCTAssertEqual("fooWithAutoClosure foo2 3", fooWithAutoClosure(a: foo2(i1: 1, i2: 2)))
}
언급URL : https://stackoverflow.com/questions/24102617/how-to-use-swift-autoclosure
'programing' 카테고리의 다른 글
| 스택 트레이스를 코코아 콘솔/로그로 출력하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
|---|---|
| VBA를 사용하여 현재 연도를 얻는 방법 (0) | 2023.04.15 |
| Swift 딕셔너리에 키가 포함되어 있는지 확인하고 해당 값 중 하나를 가져옵니다. (0) | 2023.04.15 |
| 저장하지 않고 저장 내용 확인 (0) | 2023.04.15 |
| SQL Server Management Studio에서 테이블에 인덱스를 추가할 수 없습니다. (0) | 2023.04.15 |