> Le 22 mars 2016 à 21:25, Brent Royal-Gordon <br...@architechies.com> a écrit : > >> These may be compact, but some programmer may fell that they are not in >> control: do these "stdlib" seq(), c.filter() pre-calculate all the entries >> (wasting precious cpu cycle if one break out early) or are each value >> dynamically created? Having an explicit legacy loop format gives a feel of >> control. So something like >> >> for i from 2 to 1_000_000 by 1 where i % 2 != 0 while foundCount < 5 { >> print(i); foundCount +=1 } >> >> sounds less magical and seems easier to predict than >> >> for i in 2.stride(to:1_000_000, by:1).filter({ $0 % 2 != 0}).prefix(5) { >> print(i) } >> >> and is still quite readable, even if it mixes for loop, while loop and even >> simple condition. > > First of all, this example sucks. There are *many* ways to write it with > existing features which would be more understandable than the pile of random > code in your `for` loop. Here are a few: > > for i in stride(from: 2, to: 1_000_000, by: 1) where i % 2 == 0 { > print(i) > foundCount += 1 > if foundCount >= 5 { break } > } > > for i in stride(from: 2, to: 1_000_000, by: 2) { > print(i) > foundCount += 1 > if foundCount >= 5 { break } > } > > for i in stride(from: 2, to: 1_000_000, by: 2).prefix(5) { > print(i) > } > > I know you're trying to illustrate some features you'd like on the `for` > loop, but by choosing this example you're not realy challenging your proposal > enough for its disadvantages to be illustrated well. For instance, one thing > `stride` cannot currently do is apply a step that doesn't involve addition, > for instance by multiplying the number. But your `by` keyword suffers from > the same problem! To really add anything new, your proposal would have to be > vastly more complicated than what you describe here. It's not fair to say > "look how much simpler this is" while sweeping the actual complexity under > the rug.
I agree with the qualitative you used against my example, but not sure it was necessary to say it out loud. The main thing I was trying to illustrate is the at glance interpretation and possible "fear" that the for in construct can give. The for in, at least to me, strongly suggest pre-allocated array and not plain iteration. Forgetting one instant about the legacy for(;;)-from/to/by, if Swift had two for loop variants: for element in array {} // Error if used with stride/range for element iteratingOver iterator {} // Error if use with array (like one generated by filter() It could help putting my irrational fear away. Yes, we can probably write the second as something like: iterationOver(iterator) { closure; } but then you cannot use break nor continue. The example was in no-way a pro-from/to/by, as this format seem limited on multiple fronts, but it is the current pre-proposal format suggested by Ted based on MatLab syntax. > >> Sorry if the example is a bit dumb as is; but I was too lazy to provide some >> nice code instead of the simple print. >> Can anyone tell if the filter.prefix above is lazy and that each number is >> create one by one? >> The fact that using 1_000_000 above caused my playground to crash, seems to >> indicate that the list of number is pre-generated. > > Yes, I can tell you without looking at anything that the second example is > greedy. `stride` acts lazy (it returns an instance which, when iterated over, > produces the values), but `filter` is greedy unless you explicitly use > `lazy`. If you don't know this, you can tell by looking at `filter`'s return > type, which is an Array. > > Your "explicit" syntax, on the other hand, seems totally out of control. > Where do these features come from? What happens when you find something else > you want to do in a loop? Do you invent another keyword and give it a new > syntax? This *still* doesn't give you enough flexibility to express a `for` > loop which doubles the number; is that going to require a new keyword? How > many keywords is it going to take? Is anyone ever going to learn what all > these keywords mean? Are you going to have to re-read The Swift Programming > Language to decode every moderately complicated `for` loop? So many questions for a single line of code. I do not think, i have invented any keyword, the from/to/by have been part of the pre-proposal for a while. The where can already be used with the for in. The while already exist but is not associated with the for in. So by my count, I introduced 0 new keyword, and 1 new syntax: allowing while to be tagged against a for. Putting the ‘while’ as part of my example was to cover a common case of for(;;) which came to mind where people use two conditions: an array upper bound, and an early exit (usually somethingFound). In C, the for (;;) is way too flexible and we certainly do not want that full flexibility in Swift loop structure, but I do believe that the for/in/while can provide clarity of the code intent than a for/in/if/break cannot. > > (And how am I supposed to mentally parse your sea of undifferentiated > alphanumerics? Punctuation in a programming language helps you understand the > role of each part of it; your proposal's lack of punctuation makes it > difficult to read.) That’s true, there are not that many multiple keyword statement in Swift. Only one coming to mind is the: guard let x = o else {} At least I didn’t go with textual operator: for i from 2 to 1_000_000 by 1 where i modulo 2 notEqualTo 0 while foundCount lessThan 5 { print(i); foundCount incrementedBy 1 } Dany > The function/method-based approach requires a little more syntax and a little > more understanding of what's going on. But has huge advantages that I think > you're unfairly ignoring: > > * It is simple. The `for` loop itself is quite uncomplicated. The only extra > features it has are the `case` clause, which can't be easily duplicated in > another way, and the `where` clause, which I've honestly never been totally > happy with. > * It is reusable. Calls like `stride`, `filter` and `prefix` can be used even > outside a `for` loop. > * It is extensible. If you need something new, you can add it, and it will be > just as accessible as anything the standard library's designers dreamed up. > * It is documentable. By using functions and methods instead of keywords, > it's easier to look up what a particular feature does. > * It is sustainable. If we have some kind of really specific looping > mechanism like you propose, every little feature we want will need a specific > design, evolution proposal, and implementation by the compiler team. That is > a completely unrealistic plan. Not even the C `for` loop took this > approach—it provided a *general* mechanism for plugging your own logic into a > loop. > > Ultimately, piling on new keywords every time you think of a tiny variation > is simply bad language design. Taking this approach would be foolhardy. > > -- > Brent Royal-Gordon > Architechies > _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution