"you can pass an autoclosure to an autoclosure” This is very surprising to me! I think that should be an error… When I write an argument of type `@autoclosure () -> T`, only arguments of type `T` ought to be accepted.
> On Jul 1, 2017, at 3:50 PM, Adrian Zubarev <[email protected]> > wrote: > > It’s not about whether I should use these like this or not. It’s about that > you can pass an autoclosure to an autoclosure (where the metatype is the same > as a normal closure), but you cannot pass a normal closure to an autoclosure. > @escaping making things even worse. When using Void as a return type Xcode > will provide you an additional completion option which only will result in an > error! > > func foo(_: @autoclosure () -> Void) { } > > func bar(_ test: @autoclosure () -> Void) { > foo(test) // works > } > > func baz(_ test: @autoclosure @escaping () -> Void) { > print(type(of: test)) // prints `() -> ()` > foo(test) // error because it's `@escaping` > } > > let closure: () -> Void = {} > > bar(()) > > bar(closure) // error > > // Suggested autocompletion by Xcode which results in an error > bar { > <#code#> > } > Long story short autoclosure is bugged and deserves this fix. > > Here a few examples where I’m using the mentioned non-generic extension > instead of an if statement: > > self.shouldPop.whenTrue(execute: self.toView.isUserInteractionEnabled = false) > > ($0 == .end).whenTrue(execute: completion) > (!option.isInteractive).whenTrue(execute: sendEvents) > There are other cases where I’d use it, but I cannot because the generic > autoclosure function simply does not work as I’d expect it to work: > > @discardableReuslt > func whenTrue<T>(execute closure: @autoclosure () -> T) -> T? { > if self { return closure() } > return nil > } > > > > -- > Adrian Zubarev > Sent with Airmail > > Am 2. Juli 2017 um 00:23:43, Jaden Geller ([email protected] > <mailto:[email protected]>) schrieb: > >> I feel strongly that you shouldn’t be using autoclosure in these cases. >> Instead, write `true.whenTrue { … }` and `true.whenTrue(myClosure)`. >> >>> On Jul 1, 2017, at 3:17 PM, Adrian Zubarev <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> I clearly disagree with your point. Autoclosure supposed to be a >>> syntactically convenience feature to omit braces, which as a consequence >>> needs to disable arguments. However it is not said that you cannot pass a >>> closure with the same signature to the autoclosure, which currently is not >>> possible unless it’s another autoclosure. This doesn’t feel right at all. >>> >>> func foo(_: @autoclosure () -> Void) {} >>> >>> func bar(_ test: @autoclosure () -> Void) { >>> foo(test) // works >>> } >>> >>> let closure: () -> Void = {} >>> >>> foo(closure) // error >>> Here is another example where autoclosure takes over and produces false >>> result even when the correct overload is present but the resolution ends up >>> picking an autoclosure. >>> >>> extension Bool { >>> >>> /// #1 >>> func whenTrue(execute closure: () -> Void) { >>> if self { closure() } >>> } >>> >>> /// #2 >>> func whenTrue(execute closure: @autoclosure () -> Void) { >>> if self { closure() } >>> } >>> >>> /// #3 >>> func whenTrue<T>(execute closure: @autoclosure () -> T) -> T? { >>> if self { return closure() } >>> return nil >>> } >>> } >>> >>> let test: () -> Void = { } >>> // #3 wins and produces a wrong type () -> (() -> Void)?, but I expect #1 >>> here >>> // () -> Void? >>> true.whenTrue(execute: test) >>> A syntactical convenience feature should not disable explicitness! >>> >>> >>> >>> >>> -- >>> Adrian Zubarev >>> Sent with Airmail >>> >>> Am 1. Juli 2017 um 19:46:55, [email protected] >>> <mailto:[email protected]> ([email protected] >>> <mailto:[email protected]>) schrieb: >>> >>>> >>>> >>>> On Jun 30, 2017, at 1:48 AM, Adrian Zubarev via swift-evolution >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> >>>>> Well as Jordan Rose said on the linked SR, option (1) will probably never >>>>> happen. Option (3) only makes sense if all of the options are supported >>>>> (in that case there wouldn’t be any need for explicit @autoclosure, which >>>>> could simply be merged into the closure type), or (2) is NOT supported so >>>>> that one could pass a default autoclosure. >>>>> >>>>> It leaves us only with (2), which is potentially a (small) breaking >>>>> change, but it also feels more like a fix. I cannot imagine anyone is >>>>> wrapping whole closures with auto closure, nor do I think a ‘convenience’ >>>>> operation should disable the explicit ability to pass in a closure with >>>>> the same signature. The latter feels like a bug. Furthermore I think most >>>>> code that relies on this is already doing something like. >>>>> >>>>> func bar(_ closure: @autoclosure () -> Int) { foo(closure)} >>>>> >>>>> func foo(_ closure: () -> Int) >>>>> But this is only an assumption of mine. >>>>> >>>>> Theoretically it suppose to work the other way around, right? Again >>>>> @autoclosure supposed to be a syntactical convenience feature which >>>>> implies that it won’t disable *too* much from the closure type. >>>>> Disallowing arguments is logical consequence but not the other issues I >>>>> mentioned here and in the SR. >>>>> >>>>> — >>>>> >>>>> One question: Do we need to go through a full evolution process for pitch >>>>> (2) or is a bug report enough here? >>>>> >>>> Surely the former—I'm fully against this change, and imagine others are >>>> also. Autoclosure exists to provide opt-in lazy evaluation of values by >>>> wrapping them in a closure. I think it's semantically incorrect to accept >>>> an already wrapped value here, and adding this sort of implicit conversion >>>> can introduce potential ambiguity when used with generic functions. >>>> >>>> Very large -1. >>>>> >>>>> >>>>> -- >>>>> Adrian Zubarev >>>>> Sent with Airmail >>>>> >>>>> Am 30. Juni 2017 um 00:59:45, Beta ([email protected] >>>>> <mailto:[email protected]>) schrieb: >>>>> >>>>>> These are all interesting ideas at first blush, but introduce some >>>>>> oddities into the type system >>>>>> >>>>>> 1. We accept this 😳. If we were to take this as an official language >>>>>> change it would mean that we would allow coercing T to (_) -> T by >>>>>> emitting a closure that takes an argument list (of arity given by the >>>>>> contextual type) that we throw away anyways. I would much prefer we >>>>>> diagnose this instead. @autoclosure is a syntactically convenient way >>>>>> to ask for laziness - that’s it. >>>>>> >>>>>> 2. Doing this collapses overloads on @autoclosure >>>>>> >>>>>> func foo(_ f : @autoclosure () -> String) {} >>>>>> func foo(_ f : () -> String) {} >>>>>> >>>>>> >>>>>> Which is fine by me except for the code you would break that relies on >>>>>> this. I don’t see a reasonable migration path here - perhaps you have >>>>>> one in mind. >>>>>> >>>>>> 3. @autoclosure is a parameter attribute. Allowing it to appear in >>>>>> other positions is redundant and doesn’t actually accomplish anything >>>>>> outside of maintaining consistency with the first point. >>>>>> >>>>>> I hope I don’t come off as too harsh. It’s just a little shocking to me >>>>>> that we accept the code in the linked SR. >>>>>> >>>>>> ~Robert Widmann >>>>>> >>>>>>> On Jun 24, 2017, at 9:10 AM, Adrian Zubarev via swift-evolution >>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> Hello folks, >>>>>>> >>>>>>> Here is a quick and straightforward pitch about @autoclosure. Currently >>>>>>> the attribute indicates that the caller has to pass an expression so >>>>>>> that the braces can be omitted. This is a convenient behavior only, but >>>>>>> it also has it’s shortcomings. >>>>>>> >>>>>>> I would like to propose an extension of that behavior. >>>>>>> >>>>>>> >>>>>>> 1. Allow access to arguments and shorthand argument names: >>>>>>> // Bug: https://bugs.swift.org/browse/SR-5296 >>>>>>> <https://bugs.swift.org/browse/SR-5296> >>>>>>> func foo(_ test: @autoclosure (Int) -> Int = { $0 }) { >>>>>>> print(test(42)) >>>>>>> } >>>>>>> >>>>>>> // Convenient access using shorthand arguments >>>>>>> foo(Int(Double($0) * 3.14))) >>>>>>> >>>>>>> 2. Make @autoclosure only wrap when necessary: >>>>>>> func bar(_ test: @autoclosure () -> Int) { >>>>>>> print(test()) >>>>>>> } >>>>>>> >>>>>>> let test = { 42 } >>>>>>> >>>>>>> // function produces expected type 'Int'; did you mean to call it with >>>>>>> '()'? >>>>>>> bar(test) >>>>>>> >>>>>>> 3. Extend @autoclosure to closure types in general (this change is for >>>>>>> consistent alignment): >>>>>>> // Note how we're using the shorthand argument list for this expression >>>>>>> let uppercaseWrapper: @autoclosure (String) -> String = $0.uppercased() >>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Adrian Zubarev >>>>>>> Sent with Airmail >>>>>>> >>>>>>> _______________________________________________ >>>>>>> swift-evolution mailing list >>>>>>> [email protected] <mailto:[email protected]> >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>> >>>>> >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] <mailto:[email protected]> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >> > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
