Page 1 of 1
How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 10:52 am
by Joubarbe
I often find myself - in complex code - calling a function in a ForEach that also has a ForEach on the same list.
Code: Select all
Global NewList foo()
For i = 1 To 10
AddElement(foo()) : foo() = i
Next i
Procedure FindFoo(int)
ForEach foo()
If foo() = int
ProcedureReturn @foo()
EndIf
Next
EndProcedure
ForEach foo()
Debug foo()
FindFoo(5)
Next
Infinite loop.
I'm wondering if you guys had some safety net to avoid that. I'm tempted to Push/PopListPosition() every time after ForEach and before Next, with a custom macro... or just be careful

(but infinite loops can be tricky to debug)
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 11:07 am
by RASHAD
Maybe
Use
Break to get out
Code: Select all
ForEach foo()
x+1
Debug foo()
FindFoo(5)
If x >= 100
Break
EndIf
Next
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 11:49 am
by Joubarbe
But then you don't do what you're supposed to do. You never get past foo(5).
Code: Select all
ForEach foo() : PushListPosition(foo())
Debug foo()
FindFoo(5)
PopListPosition(foo()) : Next
Kinda neat, no?
Or I would have to keep track of list index, like if I was browsing an array. Hmm...
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 11:52 am
by Axolotl
Hi,
maybe you can make the loop inside the procedure a little more secure with the use of:
Code: Select all
PushListPosition(List())
; ... do your stuff....
PopListPosition(List())
Adapted to you example:
Code: Select all
Procedure FindFoo(int)
Protected result
PushListPosition(foo())
ForEach foo()
If foo() = int
; ProcedureReturn @foo()
result = @foo()
break
EndIf
Next
PopListPosition(foo())
ProcedureReturn result
EndProcedure
Example From Help :
Code: Select all
; A simple duplicate elimination using a nested iteration
;
ForEach Numbers()
Value = Numbers()
PushListPosition(Numbers())
While NextElement(Numbers())
If Numbers() = Value
DeleteElement(Numbers())
EndIf
Wend
PopListPosition(Numbers())
Next
Ups: Too late....
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 12:03 pm
by Axolotl
I dont know what this is for, but the following shows the differences with my FindFoo() to your code above:
Code: Select all
Global *No5
ForEach foo()
Debug foo()
*No5 = FindFoo(5)
Next
Debug ""
Debug foo()
Debug PeekI(*No5)
ChangeCurrentElement(foo(), *No5)
Debug foo()
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 12:14 pm
by mk-soft
This query makes no sense to me ...
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 1:32 pm
by Fred
If a procedure modify a global list, and can be used anywhere you should protect the iteration with push/PopListPosition().
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 2:56 pm
by skywalk
I use the suggested help flow:
Code: Select all
ForEach ll()
;..some code
PushListPosition(ll())
While NextElement(ll())
;..some code
Wend
PopListPosition(ll())
Next
Be careful when calling this type of code from a thread.
Re: How to avoid infinite loops due to nested ForEach?
Posted: Fri May 02, 2025 3:21 pm
by Joubarbe
Thanks all
