For Each ... Order - FR #23798

The user docs say “A For…Each loop does not guarantee that it will loop through the values in the array in index order. Do not make any assumptions of the traversal order as it is subject to change in the future.”

This is such a drag! It takes a great language feature and makes it useless in most cases. Instead of writing

For Each line In fileContents.Split(EndOfLine)

Next

one has to write

Dim lines() As String = fileContents.Split(EndOfLine)

For i As Integer = 0 To lines.Ubound
  Dim line As String = lines(i)

Next

Now, please don’t take my demonstrative example and say there is a better way to loop through file contents, I’m just using it as an example.

Right now it seems to always do the right thing (i.e. iterate in order), but until that notice is taken out of the docs, we can’t really use For Each how most people would.

Why can’t it just guarantee order? When would anyone ever want to/or expect it to randomly choose elements from an array? i.e. a 3 line file in the above example, processing line 3 first, then 1, then 2?

[quote=123623:@Jeremy Cowgar]Dim lines() As String = fileContents.Split(EndOfLine)

For i As Integer = 0 To lines.Ubound
Dim line As String = lines(i)

Next[/quote]

You could even argue that you need an additional line more (or lines.Ubound will be called on each iteration step):

[code]Dim lines() As String = fileContents.Split(EndOfLine)

Dim ub As Integer = lines.Ubound

For i As Integer = 0 To ub
Dim line As String = lines(i)
Next[/code]

[quote=123623:@Jeremy Cowgar]
Why can’t it just guarantee order? When would anyone ever want to/or expect it to randomly choose elements from an array? i.e. a 3 line file in the above example, processing line 3 first, then 1, then 2?[/quote]
Suppose it splits the array up into chunks & hands each chunk off to a preemptive thread that processes that chunk
Whats the ordering ?

[quote=123626:@Norman Palardy]Suppose it splits the array up into chunks & hands each chunk off to a preemptive thread that processes that chunk
Whats the ordering ?[/quote]

What splits it up and what passes it off? I would expect For Each x In v to iterate 1, 2, 3 through whatever v is. If v is all out of wack and out of what I would consider a proper order, then that’s my fault for relying upon the order of v, but For Each does what I told it to.

Is there any other language (mainstream) that does not guarantee order of their for each construct? I’ve not run across one.

For example Java, .NET, and Objective C guarantee the order of a For Each loop.

JavaScript, Ruby, Python, PHP, Visual Basic.

So much so that no one even mentions that the order is guaranteed, it’s just understood. I wouldn’t be surprised if Xojo is the only language it is not.

Wikipedia’s examples even show order: http://en.wikipedia.org/wiki/Foreach_loop … Reading through all the languages listed there, none say “order is not guaranteed”.

The de facto behavior is that it currently proceeds as if you had written for i as integer = 0 to ubound() with everything that is possible to use for each with today.
But IF “for each” used an iterable object that did NOT return items in a stable order we can’t make any guarantees about “for each”
Its dependent on the iterable objects order and not one imposed by “for each”

And, should something akin to Objective-C blocks come to pass then the body of the loop could be a “block” that runs preemptively etc. And the completion order is not guaranteed under such a scenario. Nor is the starting oder as the compiler COULD split the loop into several threads & chunk out the work to be done to several of them.
Every item would still be visited & processed (satisfying FOR EACH) but not necessarily in any stable ordering

IF you need “FOR EACH” to have a stable predictable order use the other form as that you DO control explicitly
FOR EACH isn’t necessarily just short hand for “for i as integer = to ubound()”

[quote=123648:@Norman Palardy]But IF “for each” used an iterable object that did NOT return items in a stable order we can’t make any guarantees about “for each”
Its dependent on the iterable objects order and not one imposed by “for each”[/quote]
Well, iterable objects don’t exist in Xojo, or do they? If not, why not guarantee the memory layout order, like Objective C does.

Norman, so what you are saying is that if the source value given to for each doesn’t guarantee order, then the for each can not guarantee order?

If so, I believe that would be a true statement for all languages.

For Each can only iterate what it is given. If it is given a jumbled mess, then a jumbled mess will of course be the result. I don’t think anyone has a problem with that, nor would think otherwise.

The way the manual states the warning it leads one to believe at a moments notice the for each could begin pulling objects out a source array using the Random module to generate index positions.

IN PRACTICE it is first to last - but that could change

We don’t document it as such because IF it ever did / does change then we have our hands tied and CANNOT change it even if we wanted to - like I mentioned where the for loop body is a block of code that could be dispatched to multiple threads

Order is not guaranteed
If you need guaranteed order use a form that guarantees ordering

Under what situation would:

For Each i As Integer In Array(1, 2, 3)
  Print Str(i)
Next

Print:

2
1
3

?

If an array is typed to consist of iterable objects, the order should be the same as with the iterator.
In all other cases the order should be the same as the memory layout.

[quote=123657:@Jeremy Cowgar]Under what situation would:

For Each i As Integer In Array(1, 2, 3)
  Print Str(i)
Next

Print:

2
1
3

?[/quote]

For Each i As Integer In Array(1, 2, 3) // COMPILER DOES MAGIC TO LIFT THIS OUT AS A PROCESS Print Str(i) // spins off to a separate process Next
You tell me what order the OS is going to schedule them

Even if the compiler just parallelized this so the body could run on separate cooperate threads you have NO assurance that the order will be 1 , 2 , 3 in EVERY execution of this code

IF, and only if, you ONLY execute the body on a single thread can you then expect that the order might be fixed
BUT FOR EACH makes NO guarantee that it will ONLY ALWAYS & FOREVER only use ONE thread to execute the body

[quote=123662:@Norman Palardy]

For Each i As Integer In Array(1, 2, 3)
  Print Str(i) // spins off to a separate process/thread
Next

You tell me what order the OS is going to schedule them[/quote]

What order the OS schedules them has nothing to do with this discussion, that I can see. The fact remains that the For Each grabbed the first element (0) from the array, then then executed the code. What happens in the code is of no consequence. The next time code execution hits the For Each, it grabs the second element (1) and executes the loop.

Your question could be said for a for loop:

For i As Integer = 0 To ary.Ubound
    Print Str(i) // spins off to a separate process/thread
Next

Right? Or am I misunderstanding what you are getting at?

How about… make ‘for each’ work only on arrays so order can be guaranteed and introduce ‘for all’ to work on iterators if and when they come.

I don’t fully appreciate the complication with threads and blocks though. It has to do with automatic parallel processing I think.

Order is not guaranteed
If you need guaranteed order use the form of FOR that lets you rest assured order is exactly the way you expect

[quote=123665:@Norman Palardy]Order is not guaranteed
If you need guaranteed order use the form of FOR that lets you rest assured order is exactly the way you expect[/quote]

Norman, would my example For i As Integer not suffer the same fate as your For Each example?

http://en.wikipedia.org/wiki/Automatic_parallelization

No
FOR EACH might be parallelized
FOR wouldn’t be
They’re not the same language construct

However, some languages DO treat them as EXACTLY the same and one is simply shorthand for the other (as you noted)

In our case it seems it is causing programmers tedious processes and error-prone code. What you are talking about is not the order in which a for each loops through the array but you are talking about the entire process occurring totally out of order.

The whole article does not really cast a good light on automatically parallelization, for example, talking out the complexity of determining if one can put this portion of code into a parallelized process, accessing values outside of the loop, etc… It then goes on to suggest other methodologies of accomplishing the same thing that are far easier and probably much less error prone.

Does the Xojo compiler do this right now? This automatic parallelization? And if so, why only on the For Each loop?

[quote=123672:@Jeremy Cowgar]In our case it seems it is causing programmers tedious processes and error-prone code.
[/quote]

For each item as X in array
should be no more or less error prone than

for i as integer = 0 to ubound(array) dim item as X = array(i)
if it is you have other issues beyond “For vs for each”

No - the loop could be apportioned in a way the array is not traversed in order
That we have NOT parallelized for each is an implementation detail

It can be done and there are compilers that can do this today
And they do not guarantee order of execution or traversal

[quote=123672:@Jeremy Cowgar]
Does the Xojo compiler do this right now? This automatic parallelization? And if so, why only on the For Each loop?[/quote]
No
Why FOR EACH
Because you need to have SOME language construct that indicates this CAN possibly be parallelized
Different languages do it in different ways
http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach(v=vs.110).aspx