How do I clear a GROUP containing a GROUP with a DIM() Array?

HI !
Please tell me, is it possible to make a function to clear an arbitrary group with arrays?
Or are the limitations of the Clarion language preventing this from being done? Thanks !

PrintList Group
Task        Group,Dim(3)
Flag          Long,Dim(3)
Doc           Group,Dim(3)
Page            Long,Dim(3,3)
              end
            end 
          end
  Code
  ClearGroup(PrintList)  ???

clear( PrintList )
It is enough


  PROGRAM

PrintList Group
Task        Group,Dim(3)
Flag          Long,Dim(3)
Doc           Group,Dim(3)
Page            Long,Dim(3,3)
              end
            end 
          end

    MAP
    END

    CODE
    
    PrintList.Task[1].Doc[1].Page[1,1] = 1
    message( PrintList.Task[1].Doc[1].Page[1,1] )       ! Show 1 (one)
    clear( PrintList )
    message( PrintList.Task[1].Doc[1].Page[1,1] )       ! Show 0 (zero)
1 Like

Thank you. Unfortunately, no. Arrays nested in the group are cleared as strings and, in general, they will contain garbage. :frowning:

@Genricke show your code and a message or debug with the garbage?

I tested @Gustavo_Saracca code CLEAR( PrintList ) and it works for me to show Zero’s. CLEAR Groups is something I use often.

A Record and Queue are a form of Group so must work with CLEAR() e.g. CLEAR(Pre:Record) is done for adding every new Record to a File or Queue.

 CLEAR( PrintList )
 MESSAGE('Task[1].Doc[1].Page[1,1] = '& PrintList.Task[1].Doc[1].Page[1,1] &|
         '||Task[1].Flag[1] = '& PrintList.Task[1].Flag[1] &|
         '','ClearGroupTest') 
 ! Message shows =0 for both lines

A feature I don’t think is well know is you can Deep Assign an entire Numeric Array as a Constant. E.g. the below Message will show 123. It is shown in the Help on Deep Assign.

 PrintList.Task[1].Doc[1].Page :=: 123  !All[]=123 with Deep Assign :=: 123
 MESSAGE('Task[1].Doc[1].Page[1,1] = '& PrintList.Task[1].Doc[1].Page[1,1] &|
         '','ClearGroupTest .Page :=: 123 ')     
 ! Message shows =123

What can cause a problem with GROUPs is a Deep assign :=: between 2 GROUP’s that are not identical i.e. different child fields. The GROUP’s are assigned First as Strings. If there are new Child fields that are Numeric they left as the String values but assigned as binary so garbage. You need to Clear them. This is often an issue converting records.

If the only data you have inside those groups are integers, you could cheat with a STRING(SIZE(YourGroup)),OVER(YourGroup)

Then CLEAR(MyOverString,-1) will set everyting to <0>.

But some child data types might not like that too much, such as STRING().

I’d try deep assign first. MyArray :=: 0

A simple example demonstrating the problem:

  Data
gBarCode  Group
height	    Long
Print       Bool(False)
overlay     Group,Dim(3)
type          CString( 21)
text          CString(129)
            end
          end            
  Code          
  Clear(gBarCode)
  Message('TEST1: Clear(gBarCode)||' & |
          'Len(overlay[1].text) = ' & Len(gBarCode.overlay[1].text) & '|' & |
          'Len(overlay[2].text) = ' & Len(gBarCode.overlay[2].text) & '|' & | 
          'Len(overlay[3].text) = ' & Len(gBarCode.overlay[3].text))
               
  Clear(gBarCode.overlay)
  Message('TEST2: Clear(gBarCode.overlay)||' & |
          'Len(overlay[1].text) = ' & Len(gBarCode.overlay[1].text) & '|' & |
          'Len(overlay[2].text) = ' & Len(gBarCode.overlay[2].text) & '|' & | 
          'Len(overlay[3].text) = ' & Len(gBarCode.overlay[3].text))

Result:

1

In the first test, there is binary garbage in the strings (an array structure filled with spaces).
In large data structures, you need to clear each array separately - this is very inconvenient.

Question: is there any way to go through the structure of an arbitrary GROUP and clear the arrays?

clear( PrintList ) clears only first Task item, not 2nd and third. Add this line at the end and get an interesting result.
message( PrintList.Task[2].Doc[2].Page[2,2] ) ! I see 538976288

It did not work to iterate through the Group elements and clear the arrays.
Another Easter egg from the developers of Clarion ?
We need to write it down somewhere … :cry:

I am not at my Clarion machine to test this, but give it a try. For some data types, this might not be appropriate (such as STRING), but it’s OK for CSTRING.:

Data
gBarCode  Group
height	    Long
Print       Bool(False)
overlay     Group,Dim(3)
type          CString( 21)
text          CString(129)
            end
          end 
OverString STRING(SIZE(gBarCode)),OVER(gBarCode)           
  Code          
  Clear(OverString,-1) ! Should clear entire buffer to zeros.
  Message('TEST1: Clear(gBarCode)||' & |
          'Len(overlay[1].text) = ' & Len(gBarCode.overlay[1].text) & '|' & |
          'Len(overlay[2].text) = ' & Len(gBarCode.overlay[2].text) & '|' & | 
          'Len(overlay[3].text) = ' & Len(gBarCode.overlay[3].text))
               
  Clear(gBarCode.overlay)
  Message('TEST2: Clear(gBarCode.overlay)||' & |
          'Len(overlay[1].text) = ' & Len(gBarCode.overlay[1].text) & '|' & |
          'Len(overlay[2].text) = ' & Len(gBarCode.overlay[2].text) & '|' & | 
          'Len(overlay[3].text) = ' & Len(gBarCode.overlay[3].text))
1 Like

Another option could be to optionally allow the caller to provide a properly initialized buffer that you can just replace your working buffer with as needed.

It’s called a crutch. I can make them up too. There is no way to correctly clear an arbitrary Group structure. This would be a disaster even for a free programming language. Note that we get a Group filled with binary garbage without an error message. :frowning:

OK, I guess you just have to choose which crutch you’re going to use. You might be able to use Capesoft Reflection’s ClearGroup method, but I’m guessing that it would need some assistance via the extended name() attribute.

Is the only thing you want to do with this array is properly clear it?

Are you not also writing/reading the data somehow?

This code do the work.


  PROGRAM

PrintList   Group
Task            Group,Dim(3)
Flag                Long,Dim(3)
Doc                 Group,Dim(3)
Page                    Long,Dim(3,3)
                    end
                end 
            end
ClearArray  byte,dim(size(PrintList)),over(PrintList)

    MAP
    END

    CODE     
    PrintList.Task[1].Doc[2].Page[1,1] = 1
    message( PrintList.Task[1].Doc[2].Page[1,1] )       ! Show 1 (one)
    !clear( PrintList )
    clear( ClearArray )
    message( PrintList.Task[1].Doc[2].Page[1,1] )       ! Show 0 (zero)

In this case, since they are all numbers, try
Clear(PrintList,-1)

1 Like

It’s quite easy to write custom DeepClear(*GROUP) recursive procedure which clears all nested dimmed groups using standard ISGROUP, GETGROUP and HOWMANY procedures.

1 Like

I couldn’t do it. The idea was as follows:

EasyClear  Procedure(*Group MyGroup)
lCount     Long,Auto
aFieldRef  Any,Auto
pGroupRef  &Group

  Code  
  Loop lCount = 1 to 9999
    aFieldRef &= What(MyGroup,lCount)
    If aFieldRef &= Null then Break.  ! End of Group

    If Not IsGroup(MyGroup,lCount) then Clear(aFieldRef)
    else
       pGroupRef &= GetGroup(MyGroup,lCount)
       EasyClear(pGroupRef)
    end                  
  end

If you show me your version, I’ll try to explain why it won’t work… :man_facepalming:

Hi Genricke

if you have StringTheory look at the code for SerializeGroup. Bruce wrote the original version and then some time later I updated it to allow dimensioned fields using howmany() which was added in version 3.06 in March 2019.

While you are doing a different thing here, that code will show you the basic method to traverse the structure recursively, including arrays.

Sorry it is late here and I have an early start in the morning so I thought I’d just point you in the right direction. :grinning: If you have no joy I can have a look at it later in the week - but just search for howmany in the code.

hth

Geoff R

I haven’t and not going to write this proc. As I can see in your code, you do CLEAR for every field which is NOT a group.

The long version

    ! --------------------------------------------------------------------------
    ! The algorithm by brute force.
    ! --------------------------------------------------------------------------
    loop i = 1 to maximum( PrintList.Task, 1 )
        loop j = 1 to maximum( PrintList.Task[ i ].Flag, 1 )
            PrintList.Task[ i ].Flag[ j ] = value_to_set
            loop k = 1 to maximum( PrintList.Task[ i ].Doc, 1 )
                loop l = 1 to maximum( PrintList.Task[ i ].Doc[ k ].Page, 1 )    
                    loop m = 1 to maximum( PrintList.Task[ i ].Doc[ k ].Page, 2 )
                        PrintList.Task[ i ].Doc[ k ].Page[ l, m ] = value_to_set
                    end !* loop *
                end !* loop *
            end !* loop *
        end !* loop *
    end !* loop *
    
    ! --------------------------------------------------------------------------
    ! Testing Messaging.
    ! --------------------------------------------------------------------------
    loop i = 1 to maximum( PrintList.Task, 1 )
        loop j = 1 to maximum( PrintList.Task[ i ].Flag, 1 )
            s = '|Tag[' & i & '] Flag[' & j & '] -->' & PrintList.Task[ i ].Flag[ j ] &'|'
            loop k = 1 to maximum( PrintList.Task[ i ].Doc, 1 )
                loop l = 1 to maximum( PrintList.Task[ i ].Doc[ k ].Page, 1 )    
                    loop m = 1 to maximum( PrintList.Task[ i ].Doc[ k ].Page, 2 )
                        s = s & 'Tag['&i&'] Doc['&k&'] Page['&l&','&m&'] -->' & PrintList.Task[ i ].Doc[ k ].Page[ l, m ] & '|'
                    end !* loop *
                end !* loop *
            end !* loop *
            message( s )
        end !* loop *
    end !* loop *  

Do you want to write such code for each group ? :crazy_face:
The task is to implement an algorithm to clean up any GROUP structure.