Pisząc assert
w Swift zauważyłem, że pierwsza wartość jest wpisana jako
@autoclosure() -> Bool
z przeciążoną metodą w celu zwrócenia T
wartości ogólnej , aby przetestować istnienie za pośrednictwem LogicValue
protocol
.
Jednak trzymając się ściśle pytania. Wygląda na to, @autoclosure
że chce otrzymać, który zwraca a Bool
.
Pisanie rzeczywistego zamknięcia, które nie przyjmuje parametrów i zwraca Bool, nie działa, chce, żebym wywołał zamknięcie, aby je skompilować, na przykład:
assert({() -> Bool in return false}(), "No user has been set", file: __FILE__, line: __LINE__)
Jednak proste przekazanie Bool działa:
assert(false, "No user has been set", file: __FILE__, line: __LINE__)
Więc, co się dzieje? Co to jest @autoclosure
?
Edycja: @auto_closure
została zmieniona@autoclosure
f({2 >1}())
f(2 > 1)
działa. Połączenief({2 > 1})
kończy się niepowodzeniemerror: function produces expected type 'Bool'; did you mean to call it with '()'?
. Przetestowałem to na placu zabaw i za pomocą Swift REPL.func f(@autoclosure pred: () -> Bool)
Oto praktyczny przykład - moje
print
nadpisanie (to jest Swift 3):Kiedy mówisz
print(myExpensiveFunction())
, mojeprint
nadpisanie przesłania Swiftaprint
i jest wywoływane.myExpensiveFunction()
jest zatem zapakowany w zamknięcie i nie jest oceniany . Jeśli jesteśmy w trybie wydania, nigdy nie zostanie to ocenione, ponieważitem()
nie zostanie wywołane. Tak więc mamy wersjęprint
, która nie ocenia swoich argumentów w trybie wydania.źródło
myExpensiveFunction()
? Jeśli zamiast używać autoclosure, przekażesz funkcję do drukowaniaprint(myExpensiveFunction)
, jaki będzie wpływ? Dzięki.Opis auto_closure z dokumentacji:
A oto przykład, którego używa jabłko wraz z nim.
Zasadniczo oznacza to, że przekazujesz wyrażenie boolowskie jako pierwszy argument zamiast domknięcia i automatycznie tworzy ono za Ciebie zamknięcie. Dlatego możesz przekazać do metody false, ponieważ jest to wyrażenie boolowskie, ale nie może przekazać zamknięcia.
źródło
@auto_closure
tutaj używać . Kod działa poprawnie bez niego:func simpleAssert(condition: Bool, message: String) { if !condition { println(message) } }
. Użyj,@auto_closure
gdy musisz wielokrotnie oceniać argument (np. Jeśli implementowałeś funkcjęwhile
podobną do-) lub musisz opóźnić ocenę argumentu (np. Jeśli implementujesz zwarcie&&
).autoclosure
zwhile
podobną funkcją? Nie wydaje mi się, żeby to rozumieć. Z góry bardzo dziękuję.To pokazuje przydatny przypadek
@autoclosure
https://airspeedvelocity.net/2014/06/28/extending-the-swift-language-is-cool-but-be-careful/źródło
To tylko sposób na pozbycie się nawiasów klamrowych w rozmowie zamykającej, prosty przykład:
źródło
@autoclosure
jest parametrem funkcji, który akceptuje gotową funkcję (lub zwracany typ), podczas gdy generałclosure
akceptuje funkcję surowąSpójrzmy na przykład
źródło