QB64 Phoenix Edition
Best Practice for Library Building and Toolboxes - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Chatting and Socializing (https://qb64phoenix.com/forum/forumdisplay.php?fid=11)
+--- Forum: General Discussion (https://qb64phoenix.com/forum/forumdisplay.php?fid=2)
+--- Thread: Best Practice for Library Building and Toolboxes (/showthread.php?tid=2108)

Pages: 1 2 3


RE: Best Practice for Library Building and Toolboxes - RhoSigma - 10-18-2023

(10-18-2023, 03:58 PM)Kernelpanic Wrote:
Quote:@bplus -  5) Arrays should be hard indexed.  Don't DIM SHARED Array(10); instead DIM SHARED Array(0 To 10).  This prevents incompatibility if the user has OPTION BASE 1 in effect.
Wether that makes sense? If you declare an array with A( 0 To 10) you have eleven array elements, despite OptionBase 1.
To prevent this you have to fill the array with 1 to 10. With it a declaration with A(0 To 10) has no practical use.

Code: (Select All)

'18. Okt. 2023

Option _Explicit

Option Base 1

Dim As Integer feld(0 To 10)
Dim As Integer feld2(0 To 10)
Dim As Integer feld3(10)

Dim As Integer a, b, c, d

Locate 3, 3
For a = 0 To 10
  feld(a) = a
  Print Using "## "; feld(a),
Next

Locate 5, 3
For b = 1 To 10
  feld2(b) = b
  Print Using "## "; feld2(b),
Next

Locate 7, 3
For c = 1 To 10
  feld3(c) = c
  Print Using "## "; feld3(c),
Next

'Error - Out of range.
Locate 9, 3
For d = 0 To 10
  feld3(d) = d
  Print Using "## "; feld3(d),
Next

End

You must see it from the library implementors view:
If I need an array in one of my library functions which needs to have 5 elements and I do that by writing DIM a(4), hence index 0-4, but the user of my library is used to code with OPTION BASE 1 effective, then my DIM a(4) would only create a 4 elements array (1-4) and my function would error out when trying to access a(0).

The library does not know the preference of the one or other user, hence the library must make sure it works with both settings which can be achived with DIM a(0 TO 4).


RE: Best Practice for Library Building and Toolboxes - Kernelpanic - 10-18-2023

Quote:@RhoSigma - You must see it from the library implementors view:
Yes, that makes sense. The creator of a library in Basic must take into account that the index of the array can be set to one.

In C there is no such possibility. Textbooks always point out that arrays start at zero because it is abnormal. The first element of an array is the first, not the zeroth.
Basic is much closer to the general idea with Option Base 1.

I have never created a library before, I would have to do it with arrays. And then explicitly set the first element to one. If someone then declares an array with A(0 To 4) there should be a warning that arrays start with one. - Now it gets complicated.  Confused

Ok, thanks for the explanation.


RE: Best Practice for Library Building and Toolboxes - bplus - 10-18-2023

(10-18-2023, 07:15 PM)Kernelpanic Wrote:
Quote:@RhoSigma - You must see it from the library implementors view:
Yes, that makes sense. The creator of a library in Basic must take into account that the index of the array can be set to one.

In C there is no such possibility. Textbooks always point out that arrays start at zero because it is abnormal. The first element of an array is the first, not the zeroth.
Basic is much closer to the general idea with Option Base 1.

I have never created a library before, I would have to do it with arrays. And then explicitly set the first element to one. If someone then declares an array with A(0 To 4) there should be a warning that arrays start with one. - Now it gets complicated.  Confused

Ok, thanks for the explanation.

We (QB64) have ways of reading the lower and upper bounds of an array usually code lb and ub.
So generic code in library would not assume 0 or 1 but find out exactly lb = lbound(array) ub = ubound(array) and then proceed to use lb and ub.


RE: Best Practice for Library Building and Toolboxes - RhoSigma - 10-18-2023

(10-18-2023, 07:54 PM)bplus Wrote: We (QB64) have ways of reading the lower and upper bounds of an array usually code lb and ub.
So generic code in library would not assume 0 or 1 but find out exactly lb = lbound(array) ub = ubound(array) and then proceed to use lb and ub.

You miss the point here:

What you suggest is absolutely true, if an array is passed to a library function as an argument, hence the array already exists and inside the function you just need to find out its LBOUND and UBOUND.

What I'm talking about is, if the library function itself needs to create an array for internal use without knowing if the base element is set to 0 or 1, then the (x TO y) syntax makes sure the array is created as I need it inside the function.

Of course we could also go the bulky way, 1st creating the array as usual (assuming base element is zero), 2nd use LBOUND on the array to check if the base is really zero and if not (base element is one), then 3rd redim the array with one more element.
However, that would be dumb, as in most cases there are also index counters like in a FOR/NEXT which need to know the correct lb and ub.

So alltogether, in a library funcntion just DIM a(0 TO 4) and be sure it works if you later access the array in a FOR i=0 TO 4 loop.


RE: Best Practice for Library Building and Toolboxes - Kernelpanic - 10-18-2023

Yes, I have already read about LBOUND and UBOUND, but I have not used it yet.
Here is an example of how it could be applied; not tested. Is from the manual for QBasic.

Code: (Select All)

Function FeldGrenzeMax (Feld As Integer)

  Dim maximum As Integer
  Dim feldGrenze As Integer

  maximum = Feld(LBound(Feld))
  For feldGrenze = LBound(Feld) To UBound(Feld)
    If Feld(feldGrenze) > maximum Then maximum = Feld(feldGrenze)
  Next feldGrenze

  FeldGrenzeMax = maximun
End Function



RE: Best Practice for Library Building and Toolboxes - SMcNeill - 10-18-2023

You guys are missing the point here, completely.

Code: (Select All)
'This is my Program code area
Option Base 1


Cls
DoStuff




''$INCLUDE:'my file holding the library stuff below:
Sub DoStuff 'This is my poorly illustrated SUB for use in a Library
    Dim AppleJuiceSales(100)
    For i = 0 To 100
        Print AppleJuiceSales(i)
    Next
End Sub

Run the above and see what'll happen with that library code.

Now, run the code below and see what happens:

Code: (Select All)
'This is my Program code area
Option Base 1


Cls
DoStuff




''$INCLUDE:'my file holding the library stuff below:
Sub DoStuff 'This is my poorly illustrated SUB for use in a Library
    Dim AppleJuiceSales(0 To 100)
    For i = 0 To 100
        Print AppleJuiceSales(i)
    Next
End Sub

See why we explicitly define those arrays?   LBound has nothing to do with them, nor does UBound.  If the user passes you an array via a parameter, then sure, you use LBOUND/UBOUND on them...  But if you've got an array built completely inside a sub which your library code is going to use, *EXPLICITLY DEFINE THAT ARRAY*.


RE: Best Practice for Library Building and Toolboxes - SMcNeill - 10-18-2023

And this type of thing can catch you when you least expect it.  Take a look at the glitchy code below:

Code: (Select All)
'This is my Program code area
Screen _NewImage(1280, 720, 32)
$Color:32
Option Base 1


Cls , Red
Sleep
FadeDown Blue
Sleep
FadeDown Yellow
Sleep
FadeDown White
Sleep
FadeDown Black



''$INCLUDE:'my file holding the library stuff below:
Sub FadeDown (colour As _Unsigned Long)

    Dim tempScreen(_Width - 1, _Height - 1) As _Unsigned Long
    Dim fade As _Unsigned Long
    For y = 0 To _Height - 1
        fade = _RGBA32(255 * (y / _Height) * _Red32(colour), 255 * (y / _Height) * _Green32(colour), 255 * (y / _Height) * _Blue32(colour), 255 * (y / _Height))
        For x = 0 To _Width - 1
            tempScreen(x, y) = Point(x, y) And fade
        Next
    Next
    For y = 0 To _Height - 1
        fade = _RGBA32(_Red32(colour), _Green32(colour), _Blue32(colour), _Height / y * 255)
        For x = 0 To _Width - 1
            PSet (x, y), tempScreen(x, y)
        Next
    Next
End Sub

Now, it's obvious that we're making an array that works on storing and changing our screen pixels.  Screens are  _Width -1,  _Height -1 in size, so we make the array to be to that size...   Nothing wrong with that.  Right?

Except we didn't explicitly define the bounds of our array and *assumed* that it'd be BASE 0.  With Option Base 1 in effect, we generate errors and crash.

Explicitly define your arrays in library codes.  Don't assume the base you're used to working in is what the public you share your code with, is going to be using.


RE: Best Practice for Library Building and Toolboxes - Kernelpanic - 10-18-2023

Quote:You guys are missing the point here, completely.
If I understand correctly, as I mentioned it.
First example results in 101 array elements
Second example also results in 101 elements, but because of the declaration there is "out of range".


RE: Best Practice for Library Building and Toolboxes - SMcNeill - 10-18-2023

(10-18-2023, 11:12 PM)Kernelpanic Wrote:
Quote:You guys are missing the point here, completely.
If I understand correctly, as I mentioned it.
First example results in 101 array elements
Second example also results in 101 elements, but because of the declaration there is "out of range".

First example you have 100 array elements:
Option Base 1
...
Dim AppleJuiceSales(100)

With no lbound defined here, the array uses the Option Base you set to make this Dim AppleJuiceSales(1 to 100).

Which is different from the second which is 101 elements with:
Dim AppleJuiceSales(0 TO 100)


RE: Best Practice for Library Building and Toolboxes - Kernelpanic - 10-19-2023

As I mentioned - The first example would also result in 101, but due to the declaration there is an error message: "Out of range".

[Image: Out-of-range2023-10-19-023505.jpg]