> 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

Reply via email to