Problems with list in a procedure - need help

Just starting out? Need help? Post your questions and find answers here.
Harbinger
User
User
Posts: 10
Joined: Mon Mar 18, 2019 6:40 pm

Problems with list in a procedure - need help

Post by Harbinger »

The following code will be some of the first lines in a program before the main routine begins. I am setting up my lists, enumerations, and called procedures. I ran a syntax check to make sure that im doing this right:

Code: Select all

; Compartments for the SNB:
structure SNbits
    SNID.q
    SNbitflags.a
    SNptr.q
endstructure

newlist SNB.SNbits()

enumerationbinary SNbitflags
    #IsWater
    #SNType
    #IsPathNode
    #IsParcelPoint
endenumeration

; Routines for the SNB

; GetSurfaceNodeBits() retrieves the set of bitflags from the SN assigned to the ID
; The parameter is the SurfaceNode index (SNID)
procedure GetSurfaceNodeBits(dummy)
    ; go thru the SNB and look for the matching SNID in the first element of each line's structure
    while NextElement(SNB())
        if SNB()\SNID = dummy
            ; if we're at the right line, the value is the single-byte set of bitflags for 
            ; that ID
            return SNB()\SNbitflags
            break
        endif
    wend
    ; no entry was found -- return what will be processed as an error
    return -1
endprocedure
I get an error that says that "SNB() is not a list, macro,.." etc in the line "while NextElement(SNB())". But ive clearly defined it in the newlist line above the procedure. Ive checked the help and i cant see where the problem is. :|
Last edited by Harbinger on Thu Oct 02, 2025 8:38 am, edited 2 times in total.
infratec
Always Here
Always Here
Posts: 7654
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problems with list in a procedure - need help

Post by infratec »

Your list is not a parameter nor is it global.
So how should it work?
BarryG
Addict
Addict
Posts: 4196
Joined: Thu Apr 18, 2019 8:17 am

Re: Problems with list in a procedure - need help

Post by BarryG »

infratec is right. Try this:

Code: Select all

Global NewList SNB.SNbits()
Harbinger
User
User
Posts: 10
Joined: Mon Mar 18, 2019 6:40 pm

Re: Problems with list in a procedure - need help

Post by Harbinger »

Im not understanding the question or the need for global declaration. Im using the same syntax as in the help manual.

Newlist creates the list construct, and im using a Structure as its elements.

....

Ok i went back to the manual and it does say (in the NewList page, nowhere else, and "global" is not used in the example file):
"The new list are always locals, which means Global or Shared commands have to be used if a list declared in the main source need to be used in procedures. "

I hate when things are hidden in plain sight.

[UPDATE]
OK so i fixed that by declaring the SNB list as global.
Now another syntax check gives me an error "Garbage at the end if the line" referring to the line in the procedure that says "return SNB()\SNbitflags". Is this not the correct way to retrieve an element in a structure in a list?
User avatar
Mindphazer
Enthusiast
Enthusiast
Posts: 470
Joined: Mon Sep 10, 2012 10:41 am
Location: Savoie

Re: Problems with list in a procedure - need help

Post by Mindphazer »

Harbinger wrote: Thu Oct 02, 2025 8:35 am
"The new list are always locals, which means Global or Shared commands have to be used if a list declared in the main source need to be used in procedures. "
It's the same for variables, arrays and maps
MacBook Pro 16" M4 Pro - 24 Gb - MacOS 15.4.1 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
User avatar
Mindphazer
Enthusiast
Enthusiast
Posts: 470
Joined: Mon Sep 10, 2012 10:41 am
Location: Savoie

Re: Problems with list in a procedure - need help

Post by Mindphazer »

Harbinger wrote: Thu Oct 02, 2025 8:35 am [UPDATE]
OK so i fixed that by declaring the SNB list as global.
Now another syntax check gives me an error "Garbage at the end if the line" referring to the line in the procedure that says "return SNB()\SNbitflags". Is this not the correct way to retrieve an element in a structure in a list?
Use ProcedureReturn instead of Return
MacBook Pro 16" M4 Pro - 24 Gb - MacOS 15.4.1 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
infratec
Always Here
Always Here
Posts: 7654
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problems with list in a procedure - need help

Post by infratec »

Code: Select all

EnumerationBinary SNbitflags
    #IsWater
    #SNType
    #IsPathNode
    #IsParcelPoint
EndEnumeration

; Compartments for the SNB:
Structure SNbits
    SNID.q
    SNbitflags.a
    SNptr.q
EndStructure

Global NewList SNB.SNbits()



; Routines for the SNB

; GetSurfaceNodeBits() retrieves the set of bitflags from the SN assigned to the ID
; The parameter is the SurfaceNode index (SNID)
Procedure.i GetSurfaceNodeBits(dummy)
    ; go thru the SNB and look for the matching SNID in the first element of each line's structure
    While NextElement(SNB())
        If SNB()\SNID = dummy
            ; if we're at the right line, the value is the single-byte set of bitflags for 
            ; that ID
            ProcedureReturn SNB()\SNbitflags
        EndIf
    Wend
    ; no entry was found -- return what will be processed as an error
    ProcedureReturn -1
EndProcedure
To avoid ugly globals:

Code: Select all

EnumerationBinary SNbitflags
    #IsWater
    #SNType
    #IsPathNode
    #IsParcelPoint
EndEnumeration

; Compartments for the SNB:
Structure SNbits
    SNID.q
    SNbitflags.a
    SNptr.q
EndStructure


; Routines for the SNB

; GetSurfaceNodeBits() retrieves the set of bitflags from the SN assigned to the ID
; The parameter is the SurfaceNode index (SNID)
Procedure.i GetSurfaceNodeBits(dummy, List SNB.SNbits())
    ; go thru the SNB and look for the matching SNID in the first element of each line's structure
    While NextElement(SNB())
        If SNB()\SNID = dummy
            ; if we're at the right line, the value is the single-byte set of bitflags for 
            ; that ID
            ProcedureReturn SNB()\SNbitflags
        EndIf
    Wend
    ; no entry was found -- return what will be processed as an error
    ProcedureReturn -1
EndProcedure

NewList SNB.SNbits()
And ...
the current list element is changed after your call.
a break after ProcedureReturn makes no sense.
User avatar
ChrisR
Addict
Addict
Posts: 1471
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Problems with list in a procedure - need help

Post by ChrisR »

Just to add the positioning at the top of the list(ResetList) before the loop While NextElement(SNB()).
And memorize, restore the current element (Push(Pop)ListPosition) to avoid changing the current List item

Code: Select all

EnumerationBinary SNbitflags
  #IsWater
  #SNType
  #IsPathNode
  #IsParcelPoint
EndEnumeration

; Compartments for the SNB:
Structure SNbits
  SNID.q
  SNbitflags.a
  SNptr.q
EndStructure

; Routines for the SNB

; GetSurfaceNodeBits() retrieves the set of bitflags from the SN assigned to the ID
; The parameter is the SurfaceNode index (SNID)
Procedure GetSurfaceNodeBits(dummy, List SNB.SNbits())
  Protected ReturnFlags = #PB_Default
  ; go thru the SNB and look for the matching SNID in the first element of each line's structure
  PushListPosition(SNB())
  ResetList(SNB())
  While NextElement(SNB())
    If SNB()\SNID = dummy
      ; if we're at the right line, the value is the single-byte set of bitflags for 
      ; that ID
      ReturnFlags = SNB()\SNbitflags
      Break
    EndIf
  Wend
  PopListPosition(SNB())
  ; no entry was found -- return what will be processed as an error
  ProcedureReturn ReturnFlags
EndProcedure

NewList SNB.SNbits()

AddElement(SNB()) : SNB()\SNID = 10 : SNB()\SNbitflags = #IsWater : SNB()\SNptr = 1.0
AddElement(SNB()) : SNB()\SNID = 20 : SNB()\SNbitflags = #SNType : SNB()\SNptr = 1.1
AddElement(SNB()) : SNB()\SNID = 30 : SNB()\SNbitflags = #IsPathNode | #IsParcelPoint : SNB()\SNptr = 1.2

Debug GetSurfaceNodeBits(20, SNB())
infratec
Always Here
Always Here
Posts: 7654
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problems with list in a procedure - need help

Post by infratec »

Or better use ForEach if you need to scan the whole list.
User avatar
ChrisR
Addict
Addict
Posts: 1471
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Problems with list in a procedure - need help

Post by ChrisR »

yep :)
Harbinger
User
User
Posts: 10
Joined: Mon Mar 18, 2019 6:40 pm

Re: Problems with list in a procedure - need help

Post by Harbinger »

Dang you guys are more than helpful!

Im gonna look over all this code and learn as much as i can. PureBasic is not my first language so im having a hard time with even simple things.

Thanx guys!
Harbinger
User
User
Posts: 10
Joined: Mon Mar 18, 2019 6:40 pm

Re: Problems with list in a procedure - need help

Post by Harbinger »

QUESTIONS:
1. Enumerations have to be declared before using their variable in a structure? Can you not set their values after?
2. This was very helpful, esp. in the use of PushListPosition and PopListPosition. I will be searching many lists in my routines and im sure i'll be using those a lot.
3. I couldnt find anything in the help manual on using #PB_Default as a variable value. Why do we use this constant here?:

Code: Select all

Protected ReturnFlags = #PB_Default
4. Now when ReturnFlags goes back to the procedure that called it, the SNB()\SNID should have been found. I need a value to be returned that will not be a SNbitflags value if it wasnt, because that means a fatal record-keeping procedure did not add this SNID to the SNB. Is this what #PB_Default does, assume an error until we find SNID?
infratec
Always Here
Always Here
Posts: 7654
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problems with list in a procedure - need help

Post by infratec »

An enumeration is not a variable. These are constants.
The name of an enumeration is not needed. It only allows a later reuse with the highest value of the last constant as the start value +1.
You can not use an enumeration in a declaration of a structure.

You can search in lists where ever you want if you don't need the last postion.
Then you don't need push and pop. (If I remember, I used this only once in all of my codes)
You can also copy the list element structure to a new structure and return this (or better the pointer)

It depends on your preferences.
#PB_Default is -1 if I'm correct. It is also common to return 0 (#False) or #Null if no value if found.
I personally return #True and #False and the 'real' result in a 'pointer' as parameter, to avoid conflicts if the default return value can also be a valid result.
Post Reply