Swift @autoclosure 사용방법
나는 글을 쓸 때 알아차렸다.assert
Swift에서는 첫 번째 값이 다음과 같이 입력됩니다.
@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 |