Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Extended KotD #7: $INCLUDEONCE
#1
Thanks to @RhoSigma , this wonderful keyword was added into the language a few versions back.  I'm honestly surprised we haven't had more people talk about it, use it, or at least ask about it!  This is one of those commands that I consider to be a *MUST HAVE*  for anyone who does any serious library creation.

What is $INCLUDEONCE?  And what's it do for us that's so nifty?

$INCLUDEONCE is a metacommand that you place inside any of your library files, and no matter how many $INCLUDE statements they show up in, they're only included ONCE in your code.


For example, let's say I write various libraries and I have a Truth.BI file which I make excessive use of:

Truth.BI
Code: (Select All)
CONST True = -1
CONST False = 0
Now, I write a little program which saves files for me to the disk as *.SSF (Steve Special Format) files.  This save file library is going to $INCLUDE:'Truth.BI.

And I also write a little program which loads files for me from the disk, if they're *.SFF files.  This is seperate from the save library as folks may just need one of the routines and not both in their code.  This file would also have in it somewhere the need for $INCLUDE:'Truth.BI'

Now, for my own use, I want to use *both* of the routines in my program -- I want to both save and load files.  So, I write my code for the main program to look something like the following:

Code: (Select All)
$INCLUDE:'SaveSSF.BI'
$INCLUDE:'LoadSSF.BI'

... more code
And, in the IDE, I get warnings and errors and dancing bears growling and trying to eat me as I'm now trying to include Truth.BI twice in my code and that means I'm trying to define the same CONSTs multiple times.   QB64PE doesn't like that type of behavior!!

So what's the simple fix??

Let's go back and change Truth.Bi just a little:
Code: (Select All)
$INCLUDEONCE
CONST True = -1
CONST False = 0
Now, even though that library "Truth.BI" is included in multiple other libraries, and thus included in my code at multiple points, IT'S ONLY ADDED ONCE!!

The first time a file with $INCLUDEONCE in it is $INCLUDEd into your code, it's added to the code.  At each and EVERY point after that, that code is just skipped as you've already included it into your code earlier!!

$INCLUDEONCE, when placed inside a bas/bi/bm file, makes certain that the code in that file is only included one time, no matter how many $INCLUDE statements try to reference that file.

And that's a game changer right there, for anyone who writes and creates library files!  Big Grin

For everyone else, if you don't use $INCLUDE, you can basically just save the brain cells and forget this command even exists.  It ONLY affects $INCLUDE behavior, and does absolutely nothing in any other type code.  Wink
Reply
#2
Great post @SMcNeill. Absolutely agree, it's awesome and I'm grateful. I've been using it ever since it was first available. All my stuff uses it. Happily and with gratitude I am using it!

Thanks @RhoSigma - huge ergonomic quality of life improvement to the language!
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#3
This looks like a good addition and I can certainly see where it removes the need for pre-processor variable checks that can be used to prevent multiple $Include’s of the same file.  Out of curiosity, why was this added as a new keyword rather than an improvement to $Include?  Is there a use case where the old behavior would be preferred where this might break backwards compatibility?
Reply
#4
(05-18-2024, 11:57 AM)dbox Wrote: This looks like a good addition and I can certainly see where it removes the need for pre-processor variable checks that can be used to prevent multiple $Include’s of the same file.  Out of curiosity, why was this added as a new keyword rather than an improvement to $Include?  Is there a use case where the old behavior would be preferred where this might break backwards compatibility?

Let's write a couple of simple programs, and you'll see the issue instantly, I think.  Wink

First, let's write COUNT.BAS:
Code: (Select All)
Count = Count + 1
Phew!!  That's one complicated program!

Now, let's write another that is just as complicated.  Let's call this RESULTS.BAS:
Code: (Select All)
'$INCLUDE:'COUNT.BAS'
'$INCLUDE:'COUNT.BAS
'$INCLUDE:'COUNT.BAS
'$INCLUDE:'COUNT.BAS

PRINT Count
Now, obviously, this isn't any sort of complex code that's going to end up bringing a stop to world hunger or anything.  All this is, is a quick illustration of WHY $INCLUDE itself wasn't changed.  Wink

Save the first.
Run the second.
See the result is now printed on your screen as: "4".

Sometimes, for whatever odd reason, folks might want to include the same file in multiple places, or multiple times.  (I think I'd rather just make a SUB or FUNCTION and then call it multiple times, but in the end, I only write *MY* code and others have to decide what suits their styles the best.)


From the above, I think you can see why we wouldn't want to change $INCLUDE so it only loaded a file once.  Who knows how many people's old code might break with such a change?

I suppose we could've added it as a new optional paramter with $INCLUDE, but I honestly don't think that'd be any simpler or better.

$INCLUDE:'foo.bas' _ONLYONCE

^The problem I see with the above is that the file is now restriced by that $INCLUDE, which may not be the first in some list of load order.  Think of the following:

Code: (Select All)
$INCLUDE:'foo.bas'

'stuff 
$INCLUDE:'foo.bas' _ONLYONCE
Now, does that _ONLYONCE only apply from the point where it first appears onwards?  Does that mean the first $Include is valid, so it's not *really* an _OnlyOnce type deal???

I think that type of behavior would get hard to track,  debug, and deal with fairly fast.

Much better to set the line in the file you DON'T want included multiple times, and then have that forevermore flagged as a "single load" only file, I think.  Wink
Reply
#5
Ok thanks.  Seems like a pretty obscure use case, but I suppose it’s possible someone uses it that way.
Reply
#6
TBH - I've just derived it from the C/C++ style #pragma once, it's some individual thing inside the desired files, not part of the #include directive you place in the main code.
Reply
#7
$INCLUDEONCE is an excellent addition to QB64PE. In lesson 20 of the tutorial I lay out how it can be used effectively. Ever since it's introduction I've been modifying my libraries to use it. It has completely streamlined my library system.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#8
#include once has been in FreeBASIC for a while. Super useful. Glad to see it here.
It's not the having, it's the doing.
Reply




Users browsing this thread: 1 Guest(s)