[swift-evolution] [Proposal] Change guarantee for GeneratorType.next() to always return nil past end

Dmitri Gribenko gribozavr at gmail.com
Tue Mar 8 13:38:38 CST 2016


On Sun, Mar 6, 2016 at 6:16 PM, Kevin Ballard via swift-evolution
<swift-evolution at swift.org> wrote:
> On Sun, Mar 6, 2016, at 05:46 AM, Patrick Pijnappel wrote:
>
> My intuition says the extra state & branch needed for generators like
> TakeWhile could very well be optimized away in most cases if you dont make
> use of its post-nil behavior. Say TakeWhile is implemented as such:
>
> if done { return nil }
> guard let element = base.next() where predicate(element) else {
>   done = true
>   return nil
> }
> return element
>
> If the generator is then used in the common case:
>
> let generator = TakeWhileGenerator(...)
> while let element = generator.next() {
>   foo(element)
> }
>
> Should give us effectively:
>
> var base = ...
> let predicate = ...
> var done = false
> while true {
>   if done { break }
>   guard let element = base.next() where predicate(element) else {
>     done = true
>     break
>   }
>   foo(element)
> }
>
> The optimizer should see (or at least could see) `done` is never read after
> it's written to (thus removing the assignment), and therefore when checking
> the condition it can only be false (thus it can also be removed).
>
>
> This may be doable for stdlib generators, but Swift currently has a
> limitation where generic types/functions defined outside the current file
> (or module with -whole-module-optimization) are only specialized for their
> parameters if they come from the stdlib. Any such types/functions defined in
> third-party libraries (or in other files if you're not using
> -whole-module-optimization) use virtual dispatch on the generic parameters
> instead. This means that any generic GeneratorTypes defined in third-party
> libraries won't be able to optimize away this check as it won't be able to
> tell that it isn't needed.

This is a current limitation of the compiler.  The resilience effort
should make the specialization available for user-defined modules.
Thus, I don't think it makes sense to factor in the current limitation
into a long-term decision.

Dmitri

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/


More information about the swift-evolution mailing list