Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Interweaving SUB and FUNCTION
#1
With v 4.4.0, QB64PE has finally adopted to the QB45 style of allowing users to put SUBS and FUNCTIONS anywhere inside their code.

This was something which QB45 and QBASIC always allowed, but the old IDE had a habit of moving subs to their own windows (if you guys remember), and then it saved them at the end of the code.  You'd have to write code in EDIT or notepad or such, and then compile it from the command line so the IDE wouldn't move those subs/functions automagically on you, but it always has been a part of the language itself.  

It's the reason why QB45 allowed you to use a single file for $INCLUDE libraries and not have to split your work into two files to separate into the top and the bottom of the code.  Just one file at the top and you're good to go with $INCLUDE!

But there is something that folks need to be aware of, and keep in mind -- BASIC has certain commands and precompiler commands which run in a simple TOP TO BOTTOM format, so you can't think of it as the SUBs just being moved to the end of the code.

For example, let's take a look at the following code:

Code: (Select All)
Screen _NewImage(800, 600, 32)

DefInt A-Z

foo

Sub foo
    Print Len(default_variable)
    $If YEP Then
        Print "Yep"
    $Else
        Print "Nope"
    $End If
End Sub

Print
Print "And now we change the DEF and $LET precompiler values"

DefLng A-Z
$Let YEP = TRUE

Print "And let's see if anything has changed with how SUB foo behaves"
foo
Print
Print

Print "But let's see how things look after the change, if used in the main code."
Print Len(default_variable)

$If YEP Then
    Print "Yep"
$Else
        Print "Nope"
$End If

If you notice, the DEFINT is a TOP TO BOTTOM command.  So is the $IF and $LET commands.

Even though we change the DEF *after* the sub, it does nothing to change the default variable types inside the sub.

Same with the $LET.  Where the SUB is located in our code, the $LET isn't defined and thus defaults to FALSE.  Even though we set the precompiler variable AFTER the sub, it's not going to have any affect upon the SUB itself -- even if we call the SUB afterwards.

DEF statements, _DEFINE statements, $CHECKING, $IF, $LET and other such commands work on a simple precompiler TOP TO BOTTOM format.  Keep this in mind and don't think that you can $LET a variable after the SUB and have it affect the sub.  It doesn't work like that.

If you're going to create libraries which rely on DEF statements or $IF conditions, the order of which your commands come is very important.

Code: (Select All)
$LET foo = TRUE
$INCLUDE:'My_Lib.BI'

The above would carry the value of *foo* into the library.

Code: (Select All)
$INCLUDE:'My_Lib.BI'
$LET foo = TRUE

Whereas the above here wouldn't.    Make certain you guys don't get confused now that SUBS and such might be earlier in the code or in the libraries.  Program flow is still as important as ever.  It's just that where you place those SUB/FUNCTION statements has now become a lot more flexible than ever before.
Reply
#2
And to share what bplus asked in a different thread as well:

(01-29-2026, 02:21 PM)bplus Wrote: And so now can the $Include statement be put anywhere in the program as well? Though putting it at top makes the most sense for clarity.

Put it at top.   You want to put your SUBS with your DIM statements, not your DIM statements with your SUBs.

Imagine this:

Code: (Select All)
LIBRARY with the following code: 
  DIM foo
  SUB whatever
END LIBRARY

Now you write your main program

foo = 3
'$INCLUDE:'This_sexy_Library.BI'

Can you visualize what you've done here?  You've basically assembled your code so it would be like:

foo = 3
DIM foo
SUB whatever

See where you're trying to use that variable before you DIM it?  That's not what you want!



So instead, let's change the order of those statements:

Code: (Select All)
'$INCLUDE:'This_sexy_Library.BI'
foo = 3

Now what you've basically have here would be this:

DIM foo
SUB whatever
foo = 3

Since SUBS can now go between code, all is well and good and life is happy for you.  You have your variable DIMmed properly.  The sub works.  Life is good.

So put those combined library files at the TOP of your code so the DIM and such can be there first.  Putting them after your code probably isn't what you were looking to accomplish at all.
Reply
#3
I see a distinct downside with this feature. It's bound to give us future jumbled code posts...

I'm reading in the main, oops, now I'm in a sub, oops, and here I am, I'm back in the main again.



Pete

PS It sure as hell doesn't help my argument that the damn group who sang it was called, The Babys
Reply
#4
(01-29-2026, 07:12 PM)Pete Wrote: I see a distinct downside with this feature. It's bound to give us future jumbled code posts...

I'm reading in the main, oops, now I'm in a sub, oops, and here I am, I'm back in the main again.



Pete

PS It sure as hell doesn't help my argument that the damn group who sang it was called, The Babys
      In Pascal all the SUB's (procedures) have to come before the main !        For me everything before or everything after either is fine.   (or even a block before and a block after)      MIXING\interleaving  in my opinion is Bad Form whether supported or not !
Reply
#5
Lots of things can be abused if one desires.  (GOTO). Hopefully the users make use of the *good* points of the features without falling completely to the dark side of pure anarchy.
Reply
#6
'$INCLUDE, and '$INCLUDEONCE responsibly Smile
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#7
This is for me definitely a BIG advantage and something I was waiting for a long time!
So much easier to have libraries in a single include!
Thanks!!!
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#8
(01-30-2026, 03:25 PM)SMcNeill Wrote: Lots of things can be abused if one desires.  (GOTO). Hopefully the users make use of the *good* points of the features without falling completely to the dark side of pure anarchy.

Well "desires" I'm not too concerned about. Not knowing better is the issue. Of course the low amount of newcomer newbies to the forum makes my concern more theoretical than practical. In theory, someone new, and not knowing better, could easily start putting subs between statements to the point of making the program a complete mess to read and debug when help is requested.

As for the library IMPROVEMENTS, yes, I agree with others, those are outstanding.

Pete
Reply
#9
Didn't codeguy have a SUB & FUNCTION sorter program? I'm sure that could be easily adapted to ensure all the subprocedures are before / after the main procedure.
Reply
#10
(02-02-2026, 08:46 AM)luke Wrote: Didn't codeguy have a SUB & FUNCTION sorter program? I'm sure that could be easily adapted to ensure all the subprocedures are before / after the main procedure.

Too long ago for my 4K memory to access. All I remember about codeguy is Clippy threw a coffee pot at him once, and I remember that story because it would have been funnier if he threw a toaster.

I would think the QB64 IDE would contain this function, because it does sort out subs and functions in the F2 View tab.

To make one from scratch, hmm... Identifying subs, piece of cake. Identifying functions, piece of my sister-in-laws cake... rock hard fresh out of the oven. I suppose it would take eliminating all underscore keywords, by eliminating any string that started, or string segment after a colon, with an underscore. Then each QB45 keyword a string started with would have to be eliminated, including metacommands, etc. Oh, get rid of labels and line numbers, too! What's left would be the name of a function. Now add to that the function could end with an "End Sub" instead of an "End Function", and those could either be the start of a string or placed in a string after a colon.

I wonder if there is a keyword hash table in this project?  I'd jut go with step one in a hash table creation, make a comma delimited QB45 keyword list and use INSTR(). If the string segment returned an INSTR() value of zero, it's a sub or a function. Of course now that these can occur anywhere in the code, i it a call to a sub or function, or the sub or function, itself? Now method would need to check for parentheses or the optional use of "Call" to identify the differences.

Now if you will excuse me, I'm working on a program for Steve. Last week he dropped a needle in his haystack...

Pete
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Fast replace$() function mdijkens 10 1,886 04-19-2025, 06:27 PM
Last Post: mdijkens

Forum Jump:


Users browsing this thread: 1 Guest(s)