Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ARRAY declaration in GOSUB routines.
#11
(02-04-2024, 10:47 PM)SMcNeill Wrote: Looks to me like everything is working as it's supposed to.

You move that DIM up to the start of the program.

Then you have a GOSUB routine that uses it....
Then you ERASE that DIM at the end of that GSOUB routine, before the RETURN...
Then you try and GOSUB back to that routine to use it....

ERROR ERROR ERROR!!  You're out of bounds for an array that doesn't exist!!



Now, take that ERASE out of there and run it.   You now are getting an ALREADY DEFINED error.  This is expected as well:

Code: (Select All)
foo
Sub foo
    For i = 1 To 10
        Dim x(10)
    Next
End Sub

Trying to DIM an array inside a loop isn't a good idea.

Change that to REDIM, and you're golden.



So my advice here:  

1) Get rid of ERASE and CLEAR.  This is the type of glitches that are common when you use those commands.  Expect to have them pop up a lot on you as you code.
2) Change that DIM to REDIM, since you're going to be remaking this array repeatedly.
3) Then place it wherever the heck you want it.
Thank's you. I have understood where is the problem. But I don't have understood how REDIM can solve it. Furthermore, I wonder why "ERASE k, costruisci, x%" makes  k, costruisci, x% inexistent.

Code: (Select All)
OPTION _EXPLICIT
DIM a%(1)
a%(1) = 1
PRINT a%(1)
'PRINT a%(2)-----> get an error.
ERASE a%
PRINT a%(1) '------> it gives "0".
'PRINT a%(2)-----> get an error.

It seems that ERASE set a%() to 0, without deleting a%(). So, why " k, costruisci, x%" do not exist after ERASE? Of course I can reset "k, costruisci, x%" with a cicle FOR we said on the discussion about CLEAR, but I am disapponted about what I don't understand.

Furthermore, the other 2 ERASE command into the code:
'Erase IdroPixel1, IdroPixel2, idrogramma1, idrogramma2
&
'Erase idrogrammi1a24, MassimiIdrogrammi1a24, FinePioggiaIdrogrammi1a24, MassimiAssolutiIeto, IdroMaxieto%%, FinePioggiaIdrogrammi1e2, PassiFinePioggia1a24%%, IdroPixel1, IdroPixel2, idrogramma1, idrogramma2, dt!,_
'matrice1, matrice2!, MinimiMatriciQuadrante1, MinimiMatriciQuadrante2, MassimiQuadrante2

that don't give at all the problem, but they are in the DO loops allowing the program to be navigable. So, if these ERASE deletes the arrays, why I don't get errors? There must be something.

UPDATE
Making the same of the above example using a SUB, it brings to OUT OF RANGE error.

Code: (Select All)
OPTION _EXPLICIT
CALL ciao
END

SUB ciao
DIM a%(1)
a%(1) = 1
PRINT a%(1)
'PRINT a%(2)-----> get an error.
ERASE a%
PRINT a%(1) '------> get an error.
'PRINT a%(2)-----> get an error.
END SUB

That explains why I don't have problems with the ERASEs inside the main code, but I have the problem inside a SUB. Then the question is: it's a problem about ERASE, or there is something that I'm doing wrong?
Reply
#12
The problem arises that ERASE... well, it erases arrays.

FOR i = 1 to 3
    DIM x(10)
NEXT

The above is going to create an error for you, as x() is already defined on the first pass around when i = 1.  When i = 2, it can't redim the array as it's already existing.

FOR i = 1 to 3
    REDIM x(10)
NEXT

Now, with the above, there's not going to be any issue.  On the first pass x() gets dimensioned to hold 11 elements.  When i = 11, x gets redimensioned to hold 11 elements -- thus blanking all the old values of x().

FOR i = 1 TO 3
   DIM x(10)
   ERASE x
NEXT

Now, with the above, things are going to work once again as well.  You make x().  You erase x().  You make x().  You erase x().



So where did you run into a problem?

SUB foo
   DIM x(10)   <-- you defined x()
   GOSUB subroutine   <-- you jumped into the gosub
   GOSUB subroutine  <-- you jump into the gosub... but the array has been ERASED
    EXIT SUB 

subroutine:
   PRINT x(1) <-- you try and use the array to do something.  Does that array exist now??
   ERASE x   <--- and then you erased the x()
   RETURN   <-- and then you returned back to the next line
END SUB


And that's why moving the DIM from inside the subroutine to the top of the SUB errored out on you.

Your program was doing exactly what you told it to do for you.  It created an array.  It erased that array.  It then tried to use an array that no longer existed and ERROR ERROR ERROR.
Reply
#13
(02-05-2024, 12:25 PM)SMcNeill Wrote: The problem arises that ERASE... well, it erases arrays.
FOR i = 1 to 3
    DIM x(10)
NEXT
The above is going to create an error for you, as x() is already defined on the first pass around when i = 1.  When i = 2, it can't redim the array as it's already existing.
FOR i = 1 to 3
    REDIM x(10)
NEXT
Now, with the above, there's not going to be any issue.  On the first pass x() gets dimensioned to hold 11 elements.  When i = 11, x gets redimensioned to hold 11 elements -- thus blanking all the old values of x().
FOR i = 1 TO 3
   DIM x(10)
   ERASE x
NEXT
Now, with the above, things are going to work once again as well.  You make x().  You erase x().  You make x().  You erase x().

So where did you run into a problem?
SUB foo
   DIM x(10)   <-- you defined x()
   GOSUB subroutine   <-- you jumped into the gosub
   GOSUB subroutine  <-- you jump into the gosub... but the array has been ERASED
    EXIT SUB 
subroutine:
   PRINT x(1) <-- you try and use the array to do something.  Does that array exist now??
   ERASE x   <--- and then you erased the x()
   RETURN   <-- and then you returned back to the next line
END SUB
And that's why moving the DIM from inside the subroutine to the top of the SUB errored out on you.
Your program was doing exactly what you told it to do for you.  It created an array.  It erased that array.  It then tried to use an array that no longer existed and ERROR ERROR ERROR.
I don't understand.

Taking a more simple example:

Code: (Select All)
OPTION _EXPLICIT
CALL ciao
END

SUB ciao
    DIM a%(1)
    a%(1) = 1
    PRINT a%(1)'------> return "1"
    ERASE a%
    PRINT a%(1) '------> get an error.
END SUB

If I well understood (I think not) what you said, the question is the following:
DIM a%(1): creates the array;
a%(1) = 1: set the value "1";
PRINT a%(1): returns correctly "1";
ERASE a%: deletes a%
PRINT a%(1): get an OUT OF RANGE error because a%() do not longer exists.

ok. But if this is true, then even the following code should not work, but it does.

Code: (Select All)
OPTION _EXPLICIT
DIM a%(1)
a%(1) = 1
PRINT a%(1)
ERASE a%
PRINT a%(1) '------> it gives "0".

If ERASE a% delete a%(), why then the second:
PRINT a%(1): brings to "0" and not ERROR?
In this case it doesn't delete the array, but it set the values at "0".

Returning to your example:

SUB foo
  DIM x(10)  <-- you defined x()
  GOSUB subroutine  <-- you jumped into the gosub
  GOSUB subroutine  <-- you jump into the gosub... but the array has been ERASED
    EXIT SUB

subroutine:
  PRINT x(1) <-- you try and use the array to do something.  Does that array exist now??
  ERASE x  <--- and then you erased the x()
  RETURN  <-- and then you returned back to the next line
END SUB

If would work if i was not a SUB.
Reply
#14
ERASE behaves differently inside SUBS than it does in the main module.  It's why I said not to trust its behavior until you can experiment with it for a week or more and see how it interacts in all its variations. 

For instance, see below:

Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "prints 0 as the array has been reset in the main module."
foo
foo2

Sub foo
    Dim a(3)
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub

Sub foo2 Static
    Dim b(2)
    b(2) = 2
    Print b(2); "prints 2 with no problem"
    Erase b
    Print b(2); " prints 0 with no problem as this array has been reset, not erased"
End Sub

In the main module, ERASE will reset your arrays to null or zero.
In the SUB or FUNCTION, ERASE will free your arrays.
In a SUB or FUNCTION declared STATIC, ERASE only resets those arrays.  (OF course, STATIC affects other things as well, so I wouldn't recommend using it...)

This is all legacy behavior and goes back all the way to QB45.  Is it confusing?  YEP, it sure is!!

And that's why I recommend to just stay away from these old legacy commands.  

I'd rather manually write my own clear/reset routine and KNOW it's going to work in all instances, rather than to have to sit down and try and sort out when and how ERASE or CLEAR or whatnot is going to interact with my code.
Reply
#15
(02-05-2024, 01:24 PM)SMcNeill Wrote: ERASE behaves differently inside SUBS than it does in the main module.  It's why I said not to trust its behavior until you can experiment with it for a week or more and see how it interacts in all its variations. 

For instance, see below:

Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "prints 0 as the array has been reset in the main module."
foo
foo2

Sub foo
    Dim a(3)
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub

Sub foo2 Static
    Dim b(2)
    b(2) = 2
    Print b(2); "prints 2 with no problem"
    Erase b
    Print b(2); " prints 0 with no problem as this array has been reset, not erased"
End Sub

In the main module, ERASE will reset your arrays to null or zero.
In the SUB or FUNCTION, ERASE will free your arrays.
In a SUB or FUNCTION declared STATIC, ERASE only resets those arrays.  (OF course, STATIC affects other things as well, so I wouldn't recommend using it...)

This is all legacy behavior and goes back all the way to QB45.  Is it confusing?  YEP, it sure is!!

And that's why I recommend to just stay away from these old legacy commands.  

I'd rather manually write my own clear/reset routine and KNOW it's going to work in all instances, rather than to have to sit down and try and sort out when and how ERASE or CLEAR or whatnot is going to interact with my code.
ok, thank's you! Now that I'm sure there is not a formal mistake, but it is an "ERASE" singularity, I will manually write the code in order to set to "0" those arrays. But it would be interesting to understand why ERASE works like that. I suppose that SUBs existed also at time of QB45, so why they programmed the ERASE command in order to set to "0" o"null" the arrays into the main code and to delete them into a SUB? Mystery.

And im my modest opionion, I don't understand why, considered the lively band who loves QB64 and mainteins it up to date, CLEAR and ERASE commands are so neglected. I undestand that it is possible to clear/erase/set-to-0-null variables, arrays and matrixs with FOR cycles (for example), but it is also possible to clear the screen with a FOR cycle, using SPACE$, but CLS do exists. I think that it is something common to have the necessity to make, in a code, operations that CLEAR/ERASE are intended to do and that brings me to think that simple ERASE/CLEAR well-working commands should be usefull.
Reply
#16
Wow I did not know that about erase in subs in main this works fine!
Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "error! the array has been freed and erased in the SUB"

I've used erase quite a bit, guess it's always been with ones dim'd in main or shared from main. oh let's try that!

Code: (Select All)
Dim Shared a(3)
foo


Sub foo
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub
yes, no problem sharing from main!

@Bartok maybe that will work for you?
b = b + ...
Reply
#17
(02-05-2024, 02:20 PM)bplus Wrote: Wow I did not know that about erase in subs in main this works fine!
Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "error! the array has been freed and erased in the SUB"

I've used erase quite a bit, guess it's always been with ones dim'd in main or shared from main. oh let's try that!

Code: (Select All)
Dim Shared a(3)
foo


Sub foo
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub
yes, no problem sharing from main!

@Bartok maybe that will work for you?
Yes, it works. An it works also like that:

Code: (Select All)
OPTION _EXPLICIT
DIM a(3)
foo

SUB foo
    SHARED a()
    a(1) = 1
    PRINT a(1); "prints 1 with no error"
    ERASE a
    PRINT a(1); "prints correctly 0 with no errors"
END SUB

But I don't want to do that in my code, because those arrays are local and there is absolutely no need to share them with the main code.
So, if the arrays are defined in the main code, ERASE set to "0" or "null". If the array are local, ERASE deletes them. That's the reason why I don't have problems with ERASE in the other 2 ERASE command I used in the "sub" called by means of GOSUB into the main code.
Reply
#18
(02-05-2024, 02:40 PM)bartok Wrote:
(02-05-2024, 02:20 PM)bplus Wrote: Wow I did not know that about erase in subs in main this works fine!
Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "error! the array has been freed and erased in the SUB"

I've used erase quite a bit, guess it's always been with ones dim'd in main or shared from main. oh let's try that!

Code: (Select All)
Dim Shared a(3)
foo


Sub foo
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub
yes, no problem sharing from main!

@Bartok maybe that will work for you?
Yes, it works. An it works also like that:

Code: (Select All)
OPTION _EXPLICIT
DIM a(3)
foo

SUB foo
    SHARED a()
    a(1) = 1
    PRINT a(1); "prints 1 with no error"
    ERASE a
    PRINT a(1); "prints correctly 0 with no errors"
END SUB

But I don't want to do that in my code, because those arrays are local and there is absolutely no need to share them with the main code.
S, if the arrays is defined in the main code, ERASE set to "0" or "null". If the array is local, ERASE deletes it.

OK I can understand that, so Steve already pointed to sol'n of just using REDIM on temporary arrays, forget ERASE, REDIM you get 2 commands for price of 1! ;-))

BTW you can use REDIM in place of DIM for everything! Option _Explicit won't mind.
b = b + ...
Reply
#19
(02-05-2024, 02:50 PM)bplus Wrote:
(02-05-2024, 02:40 PM)bartok Wrote:
(02-05-2024, 02:20 PM)bplus Wrote: Wow I did not know that about erase in subs in main this works fine!
Code: (Select All)
Dim a(3)
a(1) = 1
Print a(1); "prints 1 with no error"
Erase a
Print a(1); "error! the array has been freed and erased in the SUB"

I've used erase quite a bit, guess it's always been with ones dim'd in main or shared from main. oh let's try that!

Code: (Select All)
Dim Shared a(3)
foo


Sub foo
    a(1) = 1
    Print a(1); "prints 1 with no error"
    Erase a
    Print a(1); "error! the array has been freed and erased in the SUB"
End Sub
yes, no problem sharing from main!

@Bartok maybe that will work for you?
Yes, it works. An it works also like that:

Code: (Select All)
OPTION _EXPLICIT
DIM a(3)
foo

SUB foo
    SHARED a()
    a(1) = 1
    PRINT a(1); "prints 1 with no error"
    ERASE a
    PRINT a(1); "prints correctly 0 with no errors"
END SUB

But I don't want to do that in my code, because those arrays are local and there is absolutely no need to share them with the main code.
S, if the arrays is defined in the main code, ERASE set to "0" or "null". If the array is local, ERASE deletes it.

OK I can understand that, so Steve already pointed to sol'n of just using REDIM on temporary arrays, forget ERASE, REDIM you get 2 commands for price of 1! ;-))

BTW you can use REDIM in place of DIM for everything! Option _Explicit won't mind.
Actually, I found that there is no need to set to 0 those arrays... because, when "CalcolaIdrogramma" is CALLed, the GOSUB subroutine "interpola:" is used twice, and in both cases the arrays are completely overwritten. I think to have put the ERASE command "automatically". Even the comment I put in the commented version doesn't explain if there were some particular reason. It says only that they had to be resetted. But it has been interesting to know this particularity of ERASE.
Reply
#20
Yah! there you go! I learned something too!
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)