How to avoid infinite loops due to nested ForEach?

Just starting out? Need help? Post your questions and find answers here.
Joubarbe
Enthusiast
Enthusiast
Posts: 711
Joined: Wed Sep 18, 2013 11:54 am
Location: France

How to avoid infinite loops due to nested ForEach?

Post 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 :D (but infinite loops can be tricky to debug)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4953
Joined: Sun Apr 12, 2009 6:27 am

Re: How to avoid infinite loops due to nested ForEach?

Post 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
Egypt my love
Joubarbe
Enthusiast
Enthusiast
Posts: 711
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: How to avoid infinite loops due to nested ForEach?

Post 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...
Axolotl
Addict
Addict
Posts: 835
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to avoid infinite loops due to nested ForEach?

Post 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....
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Axolotl
Addict
Addict
Posts: 835
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to avoid infinite loops due to nested ForEach?

Post 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() 
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
mk-soft
Always Here
Always Here
Posts: 6244
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to avoid infinite loops due to nested ForEach?

Post by mk-soft »

This query makes no sense to me ...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 18207
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: How to avoid infinite loops due to nested ForEach?

Post by Fred »

If a procedure modify a global list, and can be used anywhere you should protect the iteration with push/PopListPosition().
User avatar
skywalk
Addict
Addict
Posts: 4216
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to avoid infinite loops due to nested ForEach?

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Joubarbe
Enthusiast
Enthusiast
Posts: 711
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: How to avoid infinite loops due to nested ForEach?

Post by Joubarbe »

Thanks all :)
Post Reply