SUBS or GOSUB; for library projects, which do you guys prefer?
#1
I just wrapped up a new faster edition of my string math routines. Jack provided another source of string math code from Treebeard. Treebeard's structure have many, may subs and functions. If you added it to your routines, you would add 50 subs/functions to work with addition, subtraction, multiplication, division, and square root calculations. Now you only need to call one sub for each of those, and then those 5 subs call the other subs and functions. In my original string math, which did not include square root, everything was contained in one sub. YOU called one sub, using an operator like "+", "-", etc. and the string math operation was returned. That's a lot less clutter when adding such a routine to function in another program.

So...

Which method do you guys prefer, and what pros and cons do you see in both if SEVERAL are needed to complete a library?

For me, it's the following.

SUBS and FUNCTIONS:

Pros:
Easier for the developer to work with when debugging.
Fewer problems or no need at all to clear variables.
Advantage to passing variables by reference. It's a neat trick to change the names without additional renaming statements.
Faster to code, provided you use TYPES for many passed variables to cut down on the variable lists passed.
Can be identified in the editor (IDE) easily enough if a prefix is used for each like SUB Smath_Mult, SUB SMath_DIV, etc.

Cons:
Harder for the user to find their own program subs and functions n the mix.
Cluttered SUB/FUNCTIONS lists to sort through in the IDE.
Requires multiple CALL arguments instead of just a single call the library sub like CALL StringMath().


------------------------------------------------------------------------------------------------------------------------

GOSUBs in a single SUB

Pros:
All code contained in one easy to port sub routine.
Less project time working out passing variables; (e.g., GOSUB StringMult instead of String_Mult var1, va2, var3, etc.
Keeps the subs and function list in the editor clean, making it easier to navigate the program to which it is ported.

Cons:
More work making sure variable names do not conflict with other GOSUB routines, meaning  more need for unique variable names.
More work zeroing variables.
Possible stack space issues if too nested and a RETURN is missed.
Harder for the developer to work on in the IDE, although Alt arrow left indexing helps some.

--------------------------------------------------------------------------------------------------------------------------

Anyway, what other pros and cons come to mind and again, which method would you rather use as a library addition in your own programming projects?

Pete
Reply
#2
Pete, there's a place for an eval type math evaluater but I prefer to call each function individually
for me it's easier to see the program flow that way and it may perform better, besides, trying to figure out the workings of someone else all-in-one math evaluator can be incredibly hard, what if there's a bug but can't figure out this conglomerate of functions ?
Reply
#3
The only way you could possibly use a GoSub in a library is to have it inside a Sub or Function.
b = b + ...
Reply
#4
(08-27-2022, 07:13 PM)bplus Wrote: The only way you could possibly use a GoSub in a library is to have it inside a Sub or Function.

You can put a GOSUB library anywhere inside your main code.

Code: (Select All)
GOTO skipLibrary2022.08.27
 
proveExample:
PRINT "Here's an example of a GOSUB library!"
RETURN

skipLibrary2022.08.27:

Feel free to save that as a *.BM library file and $INCLUDE it in any of your programs, anywhere in the main module.   Just call it with GOSUB proveExample.



That said, I'd *never* go such a route.  For starters, the routine is *only* callable from the main module -- it won't work with any of your other SUB or FUNCTION modules.  Any variables in it are all in scope, so if you use a FOR i ...NEXT, you better make certain you're not corrupting the value of i elsewhere with it.  There's no easy way to free variables used in the gosub, and all-in-all, it's just one of those tools of the caveman programmer like LET, in my opinion.  I can't think of more than a handful of times in my long years of programming where I thought "GOSUB might be better than SUB for this".  When I did, it was almost exclusively just for use *inside a SUB* itself.  Wink
Reply
#5
@SmcNeill
LOL I must think that it is your work the GOTO in mid2asc.c posted by MadSciJr!
I know that it is possible to use GOTO in C, but never seen before this time.

PS: I like more the closing trend with localization of variables... so I like SUB vs GOSUB and FUNCTION vs DEF FN!
Reply
#6
(08-27-2022, 09:05 PM)TempodiBasic Wrote: @SmcNeill
LOL I must think that it is your work the GOTO in mid2asc.c posted by MadSciJr!
I know that it is possible to use GOTO in C, but never seen before this time.

Used to see it a lot in older code.  One place in particular where I recall seeing it a ton was with ON ERROR routines:

Code: (Select All)
ON ERROR GOSUB foo

GOTO skipfoo

foo:
   PRINT "ERROR!  ERROR, YOU IDIOT!!
RESUME

skipfoo:

Folks would tend to put their error handler close to the ON ERROR statement, but you didn't want it to execute with the main program code, so it tended to get wrapped in a GOTO and a label after it to make certain that it was never executed except when an error called it directly.  I recall seeing that setup in a TON of old QBASIC type routines which did error trapping.  Wink
Reply
#7
I'd prefer sub/function normally.
To prevent clutter of functions in the IDE-list, I normally prefix them per group:
function csv.read
function csv.write
function tim.date2Number
function serial.open

etc
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#8
I prefer SUBs/FUNCTIONs mainly because of the variable cons you listed under GOSUB.
Reply
#9
(08-27-2022, 09:05 PM)TempodiBasic Wrote: @SmcNeill
I know that it is possible to use GOTO in C, but never seen before this time.

Yes, "goto" exists in C, and sometimes it can be useful too, for example to get out of a deeply nested loop. Sure, that can also be solved differently, but much more complicated - and therefore more error-prone.

Here's an example of "goto" in C, but really just an example. One can easily program it differently. Many gotos . . .  Tongue

Code: (Select All)
//Goto Benutzung - 28. Aug.2022
//Prüfen der Eingabe ob Zahl

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>

int main(void)
{
    int zahl, check;    
    double pi = 3.141592653589;
    double kreisumfang, quadratflaeche;
    double zylindervolumen;
    
    wiederholen:
    printf("\nBitte waehlen Sie:\n");
    printf("10 = Kreisumfang\n");
    printf("15 = Flaeche eine Quadrats\n");
    printf("20 = Volumen eines Zylinders\n");
    printf("\n0 fuer Ende: ");
    check = scanf("%d", &zahl);
    
    //Prüft ob Eingabe eine Zahl war.
    //Liefert scanf eine 0 zurück, war es keine Zahl
    if(check == 0)
        goto keine_zahl;
    
    if(zahl == 0)
    {
        goto ende;
    }    
    else if(zahl == 10)
        goto kreis_umfang;
    else if(zahl == 15)
        goto flaeche_quadrat;
    else if(zahl == 20)
        goto zylinder_volumen;
    else goto wiederholen;
    
    kreis_umfang:
    kreisumfang = (double)10 * pi;
    printf("\nEin Kreis mit dem Durchmesser von 10cm hat einen Umfang von %4.2f cm", kreisumfang);
    exit(0);
    
    flaeche_quadrat:
    quadratflaeche = pow(15.0, 2.0);
    printf("\nBei einem Quadrat von 15cm Kantenlaenge betraegt der Flaecheninhalt: %4.2f qcm\n", quadratflaeche);
    exit(0);
    
    zylinder_volumen:
    zylindervolumen = (((20.0 * 20.0) * pi) * 30.0);
    printf("\nZylindervolumen bei einem Radius von 20cm und einer Hoehe von 30cm betraegt: %4.2f ccm\n", zylindervolumen);
    exit(0);
    
    keine_zahl:
    printf("\n\aEingabe war keine Zahl!\n");
    exit(0);
    
    ende:
    printf("\a\nUnd Tschuessi!\n");
    return(0);
}

Screenshot:
[Image: goto-BSP2022-08-29.jpg]
Reply
#10
I have to do something for Basic now! Loosely based on Ken (Excuse me)  Big Grin :

Code: (Select All)
Screen 12

Dim row As Integer, cnt As Integer, cstart As Single, cend As Single
Dim xrot As Integer, yrot As Integer, scale As Integer

'FULLSCREEN - full screen optional
cstart = 0: cend = 8 * Atn(1)
xrot = 6: yrot = 60: scale = 4
row = 1
Circle (320, 240), 15, 9: Paint Step(0, 0), 9

Do
  For i = cstart To cend Step .04
    x = 300 + (scale * 40 - (row * xrot)) * Cos(i)
    y = 200 + (scale * 40 - (row * yrot)) * Sin(i)
    cnt = cnt + 1
    Color 7: _PrintString (x, y), "I love You Basic!", 0 'display
    If cnt = Len(text$) * 8 Then cnt = 0: Exit Do
    _Display
    Color 0: _PrintString (x, y), "I love You Basic!", 0 'erase
    _Delay 0.02
  Next
Loop Until InKey$ = Chr$(27) 'escape key exit
Color 15

End
Reply




Users browsing this thread: 1 Guest(s)