Page 1 of 1

Using GOSUB

Posted: Tuesday 9th April 2019 11:40am
by Doctor Watson
I would lke to include some 'subroutines' using GOSUB but can't get it to work. I searched all of Gambas documentation (Wikis, ...) but nothing I find there works.
So here is the most simple code that works in most other Basics, but doesn’t in Gambas:
------------------------------------------------------------------------------------
' Gambas class file
Public Sub Form_Open()
GoSub Display
End

Display:
'Execute some code and return
Return
-------------------------------------------------------------------------------------
When I try to run this, I get “Missing AS in Fmain.Class:10”
'10' being the line number of Display:

This will look peanuts to an experienced Gambas user ... :shock:

Re: Using GOSUB

Posted: Tuesday 9th April 2019 12:04pm
by Cedron
I love GOSUBS. They make BASIC better than any other language. Java used to have them in the byte codes, but never implementtted and now deprecated.

Gosubs are local within a routine, just like with VB.
'==================================='
Sub This()

    blah
    blah
    
    GoSub A
    
    blah 
    
    Return
    
'-----------------------------------'
A:

    more blah

    Return

End
'==================================='
The separator lines aren't necessary, but I usually run them out to column 79.

The "Return" statement is used for both an "Exit Sub" and a gosub "Return", determined by context. The scope of variable is determined by the sub, that's what is so nice about them.

Ced

Re: Using GOSUB

Posted: Tuesday 9th April 2019 12:16pm
by Doctor Watson
Quod erat demonstrandum.
Let's see if I can put it to use.
Thanks Cedron

Re: Using GOSUB

Posted: Wednesday 10th April 2019 10:55am
by cogier
I find the trouble with GOSUB is that you can only use it in the subroutine your in. If you create another subroutine instead you can call it from any part of your program. Example: -
Public Sub Form_Open()

For iLoop As Integer = 33 To 126
  Print GetAscii(iLoop)
Next

End

Public Sub GetAscii(iValue As Integer) As String
Dim sReturn, sCase As String

sReturn = Chr(iValue) & " is ASCII value " & Str(iValue)
If IsLower(Chr(iValue)) Then sCase = " lower case"
If IsUpper(Chr(iValue)) Then sCase = "n upper case"
If IsNumber(Chr(iValue)) Then sReturn &= " and is a" & sCase & " number"
If IsLetter(Chr(iValue)) Then sReturn &= " and is a" & sCase & " letter"
If IsPunct(Chr(iValue)) Then sReturn &= " and is punctuation"

Return sReturn

End

Re: Using GOSUB

Posted: Thursday 11th April 2019 7:36pm
by Cedron
GoSubs allow you to completely avoid overburdened control structures.

I've seen them, you've seen them, "If" statements that span pages. "If" and "Do" and "Select"s and "For" structures nested way too many levels deep.

Suppose a monster like this starts growing in your code. You add features, make exceptions, etc. etc., the code grows. So, to tame it, you want to take a chunk of it out, put it aside under a label, and leave the label behind.

In most languages, other than BASIC and Assembly, you only have one choice in the kind of label to put it behind. A full blown separate procedure, complete with calling arguments needing to be defined at the call, at the definition, maybe other overhead, etc. etc. The threshold for this being rather high is the reason you see so many overburdened control structures.

Of course this solution is available in BASIC, but BASIC also gives you the GoSub. Simply cut and past the code to the bottom of your sub. Place a "Return" line in front, a label for the Gosub, your pasted code, another "Return", then put "Gosub label" where the code was and you are done. Well, you'll likely change the indentation and comment it more. If it isn't the first GoSub, the first "Return" won't be necessary. It is cheap at runtime too, (I presume this is true for Gambas as well).

So how do you decide which type of GoSub to use? It depends mostly on two criteria:

1) How many local variables are in the code that you will need to define references for?

2) Is it useful as a generally available sub?

Those criteria aren't quite independent either, so most the time the decision is easy.

Here's an example from the GamePad test program I am working on.
'=============================================================================
Public Sub TimerTick(ArgDisplayLB As ListBox, ArgTagNamesCB As CheckBox[])
        
        Dim theOutcome As Integer
        
        Do   
           theOutcome = myGamePad.GetFancyEvent()
           If theOutcome < 0 Then Break
           GoSub ShowInDisplayListBox
           GoSub HandleGamePadEvent
        Loop

        Return
        
'-----------------------------------------------------------------------------
ShowInDisplayListBox:

        ArgDisplayLB.Add(myGamePad.EventToString())
        
'---- Maybe Reduce Event Display Size

        If ArgDisplayLB.count > 1000 Then
           ArgDisplayLB.Remove(0, 100)
        Endif

'---- Position Display At End

        ArgDisplayLB.Index = ArgDisplayLB.Count - 1

        Return
        
'-----------------------------------------------------------------------------
HandleGamePadEvent:

        Dim n, v, k, e As Integer
        
        n = myGamePad.MyGPE.Number
        v = myGamePad.MyGPE.Value
        k = myGamePad.MyGPE.Kind

There are many more lines, and a few more gosubs that follow. All too big to fit in the read loop. Yes, in this case there weren't too many parameters to worry about, but keeping it local keeps it neater and the external interface cleaner.

It's really nice to have GoSubs as an option.