C5 QUEUE and GROUP TYPEs

Hi All.

According to the C5 doco I can use a GROUP,TYPE to define the structure of a QUEUE. I can’t seem to get it to work. I’m not sure if the doco is correct or it’s a bug or I’m not understanding correctly. Perhaps someone can shed some light?

In the APP/Global Data I declare a GROUP,TYPE first:

POSTCODEGT      GROUP,TYPE
Suburb            STRING(40)
State_Territory   STRING(3)
Postcode          STRING(4)
                END

and then create a QUEUE,TYPE using the GROUP,TYPE to give it (inherited) structure:

POSTCODEQT QUEUE(POSTCODEGT),TYPE
END

however when I use the QUEUE,TYPE as a parameter/prototype in a procedure, when I call that procedure I get:

Syntax Error: No matching prototype available
Syntax Error: Parameter kind does not match

If I declare the QUEUE,TYPE identically to the GROUP,TYPE no error.

Is it me or C5?

Andrew

Hi Andrew,

You’re using my preferred approach.
But I developed it after I moved on from C5
So I don’t know if it worked in C5, and I no longer have a 32 bit OS to test it …

The following program works in C10,
Can you please test it in C5.

  PROGRAM
       
POSTCODEGT      GROUP,TYPE
Suburb            STRING(40)
State_Territory   STRING(3)
Postcode          STRING(4)
                END

POSTCODEQT QUEUE(POSTCODEGT),TYPE
END

  MAP
   Dump(*PostCodeQt Q)
  END
 
MyQ POSTCODEQT
  CODE
  MyQ.Suburb = 'A'; MyQ.State_Territory = 'FL';  ADD(MyQ)
  MyQ.Suburb = 'B'; MyQ.State_Territory = 'WI';  ADD(MyQ)
                         
  Dump(MyQ)

Dump PROCEDURE(*POSTCODEQT Q) 
Ptr LONG,AUTO
  CODE
  LOOP Ptr = 1 to RECORDS(Q) 
    GET(Q, Ptr)
    MESSAGE('Rec['& Ptr &']|Suburb['& Q.Suburb &']|State_Teritory['& Q.State_Territory &']')
  END

Thanks Mark.

I followed your example and figured out what I did wrong. This is what I was doing wrong (the declaration of the queue):

MyQ QUEUE(POSTCODEQT)
END

which according to the doco is correct.
Thanks for your help again.

FWIW, I re-tested with

MyQ QUEUE(PostCodeQt)
    END   

and it works fine. So that wasn’t the issue.

I also tested with

MyQ QUEUE(POSTCODEQT)
X      LONG
    END

And that works fine too.

Might just be a C5 thing.

the code from Mark compile and run ok in cw5a

I also want to add to this - the GROUP and QUEUE definitions have to be done in the same file - at least, when you’re working .inc and .clw (handcoded) - as I can use the GROUP from another file in PROCEDURES, but not in the QUEUE - getting a undefined error

You’re probably having a scoping problem

TLDR; you should have an INCLUDE('theGroupType.inc'),ONCE at the top of your class .INC

(see Code Example at the bottom of this post)


I usually wrap these typed queues in classes
The .CLW for my class 9 times out of 10 has what I call an “empty member statement”
One that looks like
MEMBER
or
MEMBER()

vs. MEMBER('MyMainModule')

I’m talking about that classes and MEMBER statements because only the MEMBER(‘MyMainModule’) can see your global scope. The empty members see absolutely nothing, so little in fact that you may find it required to add a MAP;END just to get access to prototypes listed in BuiltIns.clw and Win32.LIB too

Since the empty member module of the class can see absolutely nothing, you have to add an INLCUDE('yada.INC') in the ctYada.CLW as it the .CLW doesn’t even know about the class it’s implementing.


Note: i use a modified Hungarian notation. IOW in my code you can assume that the following letters prepended to a label have the following meanings:

  • gt => group, type
  • qt => queue, type
  • ct => class,type
  INCLUDE('YadaGroup.inc),ONCE

qtYada      GROUP(gtYada),TYPE
            END 

ctYada      CLASS(),TYPE,MODULE('ctYada.clw'),LINK('ctYada.clw')
Q             &qtYada
CONSTRUCT     PROCEDURE() 
DESTRUCT      PROCEDURE()
Free          PROCEDURE()
Delete        PROCEDURE()
            END

 MEMBER()

 INCLUDE('ctYada.inc'),ONCE  ! the ,ONCE isn't really needed here

 MAP    ! Important as there is an implied INLCUDE('Builtins.clw'),ONCE in the map
 END 

ctYada.CONSTRUCT PROCEDURE()
   CODE
   SELF.Q &= NEW qtYada

ctYada.DESTRUCT PROCEDURE()
   CODE
   SELF.Free()
   DISPOSE( SELF.Q )

ctYada.Free PROCEDURE()
    CODE
    LOOP 
      GET( SELF.Q, RECORDS(SELF.Q) )
      IF ERRORCODE() THEN BREAK END
      SELF.Delete()      
   END 

ctYada.Delete PROCEDURE()
    CODE
    ! handle any additional DISPOSE()s here 

    ! usually I have the .Free() and .Delete() in a base class
    ! where .Delete() is a virtual method
    ! but in this case where it's all here,  this method is a bit overkill

    DELETE(SELF.Q)

Yeah it’s probably a scoping problem - but can you explain why it doesn’t work for a QUEUE - but does work for a FIELD in a class, or PARAMETERS for procedures in the class (or just any procedure) in the same INC where I tried to use QUEUE(MyGROUP) and failed?

Currently fighting with clarion to get a QUEUE based on a GROUP to work as FIELD in my CLASS - it seems to only compile by noting it as

MyClass CLASS.....
MyQ &MyQueue,PROTECTED
END

But instantiating it is being a pitty

Yes, a Queue as a property of class needs to be a reference to a queue. So you’ll want to NEW and DISPOSE of it
– see the code example I posted earlier today.
(note: it’s possible to inject an instance of the queue from elsewhere)

I’m happy to help, but it really helps when you’re specific as to any problems you’re having.

FWIW I often pass typed queues and typed queue buffers (typed groups)