Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Meta Commands
#1
Can meta commands such as option base 0 or 1 or option _explicit be set to only affect the main program and not the included libraries? If not, be a cool addition to the IDE instead of being forced to be using the defaults.
Reply
#2
Welcome to the forums!

Technically "OPTION" is not a metacommand. QuickBASIC only supported "BASE" second keyword which was only to change the first subscript to dimension an array, either zero or 1, when the programmer doesn't use a statement like "DIM A(1 TO 10) AS INTEGER". The "OPTION _EXPLICIT" is a QB64-only thing; note that other BASIC's don't carry the underscore in the same statement, although there is "$NOPREFIX" metacommand to suppress the leading underscore from QB64-only keywords.

"OPTION" is recommended used near the top of the program before any executable statements and preferably before any variable is declared or created.

A metacommand, which is not compatible with Q(uick)BASIC must begin with "$" such as "$NOPREFIX", "$CONSOLE:ONLY" or "$CHECKING:OFF". The ones compatible with Q(uick)BASIC must begin with "REM" or apostrophe, then "$" then "keyword" and then it depends such as "'$INCLUDE: 'file.bi'" or "'$STATIC". Those older metacommands must be treated like remarks, not like the QB64-only ones or the compiler throws an error.

https://qb64phoenix.com/qb64wiki/index.php/Metacommand

BTW do not use double quotation marks in any of those statements for source code, it's a tendency of mine.
Reply
#3
(11-16-2022, 03:41 AM)NasaCow Wrote: Can meta commands such as option base 0 or 1 or option _explicit be set to only affect the main program and not the included libraries? If not, be a cool addition to the IDE instead of being forced to be using the defaults.

I would say no. Steve has already lamented how Option _Explicit even effects code in libraries back at old forum.
What defaults are you being forced to use?

Default usually means something will be used if you haven't declared a preference.
Option base 1 or 0 are old compatibility Options, you can start and stop an array anywhere eg, Dim arr(-100 to 100)
b = b + ...
Reply
#4
Perhaps I have been calling them the wrong thing for a very long time.

What has happened is when I included Ritchie's QB64 Menu Library and tried to switch to OPTION BASE 1, it throws an array out of bounds inside the library when it is ran but it doesn't when the base is set to zero. So my question is with these options or commands (whatever they are called collectively), is there a way to use them only in my main .BAS file and not "bleed over" to the .BI files. Sorry if I was imprecise with my language, a great sin for a programmer  Angel
Reply
#5
(11-16-2022, 05:13 AM)bplus Wrote:
(11-16-2022, 03:41 AM)NasaCow Wrote: Can meta commands such as option base 0 or 1 or option _explicit be set to only affect the main program and not the included libraries? If not, be a cool addition to the IDE instead of being forced to be using the defaults.

I would say no. Steve has already lamented how Option _Explicit even effects code in libraries back at old forum.
What defaults are you being forced to use?

Default usually means something will be used if you haven't declared a preference.
Option base 1 or 0 are old compatibility Options, you can start and stop an array anywhere eg, Dim arr(-100 to 100)

I guess I am the odd one that really likes to use $NOPREFIX command and I also really, really like OPTION _EXPLICIT. I know it is just preference and working around it, just miss it for this program I am writing  Cool

Good point on array defining, I shouldn't be lazy to use the style I want!
Reply
#6
(11-16-2022, 11:44 AM)NasaCow Wrote: Perhaps I have been calling them the wrong thing for a very long time.

What has happened is when I included Ritchie's QB64 Menu Library and tried to switch to OPTION BASE 1, it throws an array out of bounds inside the library when it is ran but it doesn't when the base is set to zero. So my question is with these options or commands (whatever they are called collectively), is there a way to use them only in my main .BAS file and not "bleed over" to the .BI files. Sorry if I was imprecise with my language, a great sin for a programmer  Angel

Afraid not, and if you think about it for a moment, you'll see why.

Let's say you write a very simple program:

Code: (Select All)
OPTION BASE 1

REDIM text(0) AS STRING

--stuff

SUB CountLines (file AS STRING, text() AS STRING) 'counts the lines of text in a file and saves them as an array.
    OPEN file FOR BINARY AS #1
    DO UNTIL EOF(1)
        count = count + 1
        IF count > UBOUND(text) THEN REDIM _PRESERVE text(count) AS STRING
        LINE INPUT #1, text(count)
    LOOP
    CLOSE 1
END SUB

Simple enough -- you wrote a SUB which counts the lines in an text file and saves them to a string array.  Written as is, it works flawlessly.

Now, imagine a few months later, you've assured yourself that this is THE bestest best ever line counting, array storing routine, so you decide to take it out of your program and save it as "CountLines.BM"...  You share it with all your friends...

...and suddenly it's not working as advertised!!

It went from a routine inside the main BAS file to simply being one inside a BM file, and now it's not working because that OPTION BASE 1, which you *always* tend to use as default in your programs, doesn't work with the $INCLUDES.   Tongue



Coding for one's self, a lot of these ideas seem like great ideas.  Once one starts coding and releasing that code to the public however, it becomes the wild, wild west out there.  Yoiu have to try to imagine not just how people like you would use the commands, but how it'd affect people who's coding style is almost completely foreign to you, and yet they're using the language you've produced.  

If "OPTION BASE 1" were included in a *.BI file, how far should that influence reach?  Only to that BI file?  Only to the file and a similarly named *.BM file?  But what if it passes shared variables back to the main program -- would those be BASE 1 or BASE 0?  IF the main module has an array called FOO(), and $DYNAMIC is in use, then FOO() is resizable.  Now, if there's a REDIM foo() inside an $INCLUDE file, is that foo() resizeable?  Is it even the same array, or does it create a new STATIC array now?  How's the change to localized Metacommands affected it?

In the wild, wild west of open-source coding, such a command would likely break zillions of old programs.  People would start shouting, "AHHH!!  MY OLD SHIT DOESN"T WORK ANY MORE!!  FIX IT!!!"

v1.5 had a "fix" to recursive functions in it, that changed how they worked for people -- and that STILL gets folks posting about it on a regular basis asking about, "Why my shit no work no more?"  That's with just a change to ONE single keyword...   

I can't even begin to imagine how many people would faint, explode, and murder someone, if the behavior of all the MetaCommands was suddenly changed on them....
Reply
#7
Perhaps a command can be added for library writers to test for this?

CheckBase% = _OPTIONBASE

Returns 1 if OPTION BASE 1
Returns 0 if OPTION BASE 0
Returns -1 if OPTION BASE was not set

I was just playing around with OPTION BASE and arrays and I think I may have found a solution for library writers.

If I do this:

OPTION BASE 1
DIM a(100)
a(0) = 10

I get an error.

However, if I do this:

OPTION BASE 1
DIM a(-1 to 100)
a(0) = 10

all is well. As long as the first number in an array is a negative value it seems to allow the use of index 0 and 1 no matter what OPTION BASE is set to. So for arrays in libraries always start them at -1 and any setting by the programmer using OPTION BASE seems to be ignored.

Is this normal behavior or a loophole that I've found?
Reply
#8
For Library writers, I'd suggest always dimming both upper and lower bounds.

DIM a(0 to 100)

or, if you like OPTION BASE 1:

DIM a(1 to 100)

You never know what someone will have in their program where they include your library file, so it's best to be as self-contained as possible. In both cases above, it doesn't matter what the option base is, as you've explicitly defined what the upper and lower limits of your arrays are going to be. Wink
Reply
#9
Here's the transscript from the conclusion of a discussion we had with Steve, Terry and others a couple years ago on the old forum regarding the requirements for proper "Library authoring":

Quote:Steve:
    1) Subs/Functions should start with creator initial.  A Steve(tm)
library would use SM_ for naming convention.  Sure, there might
be more than one guy with the SM initials out there, but if there
is, he hasn't posted much here on the forums, and all conflicts
with SM_Xpos and TR_Xpos are instantly cleared up...
RhoSigma:
Although I mentioned this kind of ID earlier too here in this topic,
after rethinking I came to the conclusion that we don't necessarily
need IDs for SUB/FUNC names. Why?? - Every library has a specific
purpose, eg. imageprocessing, spritesheets, menu, database, sorting
etc., from that point of view the SUB/FUNC names should be unique
enough between the different library types, as the names are usually
chosen having the context of the respective library in mind. Even if
there may exist more than one library for the same purpose, eg. three
different spritesheet libs from three different authors, then still
the user will most probably decide to use just one of it, the one
which fits best for his needs.

Steve:
    2) GLOBAL Names should be self descriptive as much as possible.
SM_TextToImage is much easier to understand, remember, and use
than SM_TTI, and chances are, it's also more resistant against
accidental duplication.
RhoSigma:
Agreed, however for me it doesn't matter if the initials are
representing the authors name or the library name/type. Every author
should just be consistent on his preferred naming scheme.

Steve:
    3) COMMON variable names (such as any single digit character)
should *always* be LOCAL and TEMPORARY in scope.  Don't DIM
SHARED X, Y, I, K, M, ect...  Keep them reserved as temp
variables and they should never interfere with another user's
variables.
RhoSigma:
Totally agreed.

Steve:
    4) Unless NECESSARY, Subs/Functions should never pass values back
via the parameter.  Instead of SUB SM_MathJunk (X, Y), values
should be passed as SUB SM_MathJunk (TempX, TempY), with the next
line reading X = TempX: Y = TempY.  This practice prevents all
instances of accidental value corruption.
RhoSigma:
Agreed, however it seems you chose the easy way for you as library
implementor. I personally would leave it as SUB SM_MathJunk (X, Y)
for the public user and rather do tmpX = X: tmpY = Y internally, as
any unexperienced user could be confused, if he reads to give
"temporary" arguments to a SUB/FUNC call.
  Very important, if argument side effects are necessary/intended,
then this MUST be explicitly mentioned in the respective function
description. Also remind the potential user of such a SUB/FUNC that
he should not use extra parenthesis to make a BYVAL parameter
transfer. Also he can not give any literal values, but only
variables of the very same variable type as specified in the
parameter list, because QB64 would internally create a temporary
parameter for literals or wrong variable types, which would
compromise the intended side effect.

Steve:
    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.
RhoSigma:
Indeed, I've never thought about this one Steve, agreed.

Steve:
    6) Subs/Functions should *always* restore settings before exit.
If your sub needs a _DISPLAY to show text on the screen (such as
for a message box), check to see if the user had _AUTODISPLAY on,
and if so, restore it on exit.  _DEST, _SOURCE, _BLEND, COLOR,
Visible Screen, and lots more *can* be altered while in a sub,
but unless that's the intended purpose of the sub, it shouldn't
happen in Library code.
RhoSigma:
Totally agreed.

Steve:
    7) Useage of Global Flags/Metacommands should be avoided.  DON'T
count on DEFLNG A-Z to be set, or OPTION BASE to be 0/1, or
$DYNAMIC to be in use.  Once you share a library publicly, you'll
run into somebody who has the option set completely backwards of
what you always ASSUMED was standard.
RhoSigma:
Indeed, never count on it and never ever even think on defining it in
your library. Also, just as Terry mentioned, don't ever think on
defining CONSTs for true/false, consider it would be the same as
doing a DEFLNG A-Z in your library. Instead use type suffixes in your
library code and literal booleans 0/-1 as suggested by Terry.

I used this to condense it into some simple rules I follow in all my libraries (see links in my signature) to make them as compatible as possible. These rules are as follows (note the numbers in () which coresspond to the sections in the quote above):

Quote:- Make a section in the beginning of each SUB/FUNC where you DIM all variables (OPTION _EXPLICIT requirements), even if you usually code without it.

- (7) Use variables with type suffix & literal bools 0/-1, don't assume or set defaults such as DEFINT etc. or constants like TRUE/FALSE.

- (2) Use descriptive global variable names with prefix (in CONST, DATA, (RE)DIM/COMMON SHARED etc.).
- (5) Always hard index global/local arrays (eg. (RE)DIM arr(0 TO 10)).
- (1) Sub/Function names doesn't need prefixes but names must be clear in the library's context.

- (4) Avoid argument side effects (use temp vars), but mention it explicitly in the docs if those are intended for some reason.
- (3) Keep ordinary 1-2 letter variables temp/local to SUB/FUNC, see also (2).
- (6) Restore changed modes (_SOURCE, _DEST, _PRINTMODE etc.) before exit/end SUB/FUNC.
Reply
#10
Thumbs Up 
That looks very interesting thank RhoSigma!
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)