Page 1 of 1

is this correct behaviour of procedurereturn in a foreach ?

Posted: Mon Jul 29, 2019 3:26 am
by sculptor
Hi, could somebody explain why when i do a procedurereturn from inside a foreach over a list. The second time i call the procedure it seems to have remembered where i was in the list instead of starting the foreach loop again. So i had to put in the resetlist to correct it.
It's a kind of nooby question because i have been a long time away from purebasic. But it took me a long time to find the problem in my code.

Code: Select all

Procedure.i find_the_word(word.s);word is passed from a different list,  foreach
  Protected tmp.i = 0
  
  ForEach dict_contents() ;loop thru a global  dictionary of words (i would have thought the foreach would set back to element 0)
    tmp.i + 1  
    
    If dict_contents() = word.s ;is the word in the dict?
                                
      Debug tmp.i  ; here on the second call to the procedure list element has been remembered
      ResetList(dict_contents()) ; so unless i do this reset i have the wrong count in tmp
      ProcedureReturn tmp.i
        
    EndIf 
  Next
  Debug "tmp here is= " + tmp
  
  ProcedureReturn 0
EndProcedure

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 3:50 am
by collectordave
That is the way lists behave.

I imagine a list is like a shopping list with a little arrow next to the item in the list you are looking at, it is up to you to move that arrow. You have the list declared as Global so the arrow can be moved anywhere in your programme.

If you use ResetList(dict_contents()) before the ForEach it should be Ok.

collectordave

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 3:58 am
by sculptor
Thanks for the info collectordave

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 4:07 am
by skywalk
Much easier if you use EnableExplicit and post working code. :idea:

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 5:03 am
by nco2k
collectordave wrote:If you use ResetList(dict_contents()) before the ForEach it should be Ok.
you dont have to use ResetList() because ForEach already resets the list.

@sculptor
i cannot reproduce your issue. its hard to help without a working example that showcases your problem.

c ya,
nco2k

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 5:35 am
by Demivec
@sculptor: I cannot reproduce your issue. Here is the sample code I used with the line that contains ResetList() commented out:

Code: Select all

EnableExplicit
Global NewList dict_contents.s()
Define h, i, j, k
#ASCII_A = 'A'
#ASCII_Z = 'Z'

;fill list with 456976 4 letter words "AAAA" through "ZZZZ"
For h = #ASCII_A To #ASCII_Z
  For i = #ASCII_A To #ASCII_Z
    For j = #ASCII_A To #ASCII_Z
      For k = #ASCII_A To #ASCII_Z
        AddElement(dict_contents())
        dict_contents() = Chr(h) + Chr(i) + Chr(j) + Chr(k)
      Next
    Next
  Next
Next


Procedure.i find_the_word(word.s);word is passed from a different list,  foreach
  Protected tmp.i = 0
  
  ForEach dict_contents() ;loop thru a global  dictionary of words (i would have thought the foreach would set back to element 0)
    tmp.i + 1  
    
    If dict_contents() = word.s ;is the word in the dict?
                                
      Debug tmp.i  ; here on the second call to the procedure list element has been remembered
      ;ResetList(dict_contents()) ; so unless i do this reset i have the wrong count in tmp
      ProcedureReturn tmp.i
        
    EndIf 
  Next
  Debug "tmp here is= " + tmp
  
  ProcedureReturn 0
EndProcedure

Define a$
Repeat
  ;generate random 4 letter word
  a$ = Chr(Random(#ASCII_Z, #ASCII_A)) +
       Chr(Random(#ASCII_Z, #ASCII_A)) +
       Chr(Random(#ASCII_Z, #ASCII_A)) +
       Chr(Random(#ASCII_Z, #ASCII_A))
  Debug a$
  Debug "---result of search 1: " + find_the_word(a$)
  Debug "---result of search 2: " + find_the_word(a$)
  Debug "---result of search 3: " + find_the_word(a$)
  a$ = InputRequester("", "Press Enter to repeat, Q to quit.", "")
Until a$ = "Q" Or a$ = "q"
The test code creates a list of 456976 unique words. If a previous list position was used in the procedure than it would never find the word in additional searches. It produces consistent results as is.

The lines you have documented with "here on the second call to the procedure list element has been remembered", will only be reached if a match is found and so will always contain the same element out of a set of unique elements. Your conclusion that this is somehow evidence of buggy behavior is incorrect.

Re: is this correct behaviour of procedurereturn in a foreac

Posted: Mon Jul 29, 2019 7:51 am
by sculptor
Thank you all for your replies which made me go back again and look at my code.
It turned out to be one of those horrible self inflicted bugs, I was loading the dictionary repeatedly which caused the list to keep growing.
By putting a resetlist() in this procedure it appeared to fix the problem. :oops:

Thanks again for your wonderfully quick responses.