Board Logo
« SUB, GOSUB, FUNCTION, Useful ERROR Messages »

Welcome Guest. Please Login or Register.
Jan 18th, 2018, 3:53pm


Conforums Terms of Service | Membership Rules | Home | Search | Recent Posts | Notification | Format Your Message | Installation FAQ

This board is not meant for general discussion, it is meant for posting articles to help others.
For general discussions use the appropriate board, which best describes your problem area.

« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: SUB, GOSUB, FUNCTION, Useful ERROR Messages  (Read 13246 times)
Welopez
Moderator
ImageImageImageImageImage


member is offline

Avatar

Never let your beliefs get in the way of learning.


PM

Gender: Male
Posts: 4407
xx SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Thread started on: Feb 5th, 2005, 12:13pm »

One of the reasons we use SUB (sub-routines), GOSUBS, and FUNCTIONS, is because they allow us to reuse blocks of code, without retyping them. Less typing means fewer typos which may be frustrating to debug. Once you are satisfied with the results of a block of code, you may want to "copy and paste" to another program to avoid re-inventing the wheel. Most blocks are designed to "do something" with variables, numeric or string, within the main program. However, you may be surprised by the "scope" of a variable; that is, whether it is local to a block of code and not seen by the main program, or GLOBAL and may be used throughout the program. I suspect the reason behind limiting scope originated when software began being developed by teams of coders, with each programmer being assigned responsibility for a small module or purpose. It simply would not do to have variables created which might be in use elsewhere, unless absolutely required.

Whether you're an old hand at coding, a beginner, or an experienced coder making the transition from another version of Basic, you may initially experience some confusion understanding the differences between SUB, GOSUB, and FUNCTION statements in JB. Alyce Watson has some great explanations at the Liberty BASIC Programmers Encyclopedia. Most of the features of LB are equally applicable to JB and you should bookmark the site for valuable tips and explanations.

Find direct links to the articles in the post below.

Some values are GLOBAL by default and may be used anywhere within a program. Examples of these are listed in the help files under the topic SUB. Variables which are not global, may be declared at the beginning of your program using the GLOBAL statement:

GLOBAL diameter, height, name$... etc.

Use caution when declaring variables to have a GLOBAL scope. These variables can be modified in sub-routines and functions, returned to the main program, and may produce unexpected (even confusing!) results elsewhere. Limiting scope is great for large businesses with a team of programmers in their IT department, but what about the little guy at home? I hope this little introduction may clear up some questions.

Code:
'SUB/GOSUB/FUNCTION/Error NOTICE

[doDemo]
TIMER 0  'Turn off timer if used to end SELECT CASE.
CLS 'Begins every demo with a clear screen.

'Branch to choice.
PRINT "Do you wish to calculate..."
PRINT TAB(5); "the area of a circle?  A"
PRINT TAB(5); "the area of a square?  B"
PRINT TAB(5); "the area of a triangle?  C"
PRINT TAB(5); "nothing.  I wish to quit.  Q"
PRINT
INPUT "Please enter your choice...  "; resp$
resp$ = UPPER$(resp$)  'Convert to capital letter.
'IF resp$="Q" THEN [close]

SELECT CASE resp$
    CASE "A"
    [circle]
    PRINT
    PRINT "Calculate the area of a circle."  'Using FUNCTION
    INPUT "Enter the radius in inches (1/2 the diameter): "; resp$
    IF resp$ = "" THEN GOSUB [knucklehead] : GOTO [circle]
    rad=VAL(resp$)
    IF rad <= 0 THEN GOSUB [knucklehead] : GOTO [circle]
    PRINT "The area of the circle is "; sqcir(rad); " sq/inches."
    'The function name is "sqcir", the value passed is "rad"

    CASE "B"
    [square]
    PRINT
    PRINT "Calculate the area of a square."  'Using CALL a SUB
    INPUT "Enter the length in inches of any side: "; resp$
    IF resp$="" THEN GOSUB [knucklehead] : GOTO [square]
    side=VAL(resp$)
    IF side <= 0 THEN GOSUB [knucklehead] : GOTO [square]
    CALL doSquare side  'Pass the value of "side"  byref to doSquare
    PRINT side

    CASE "C"
    [triangle]
    PRINT
    PRINT "Calculate the area of a triangle."  'Using GOSUB
    INPUT "Enter the base in inches: "; base$
    INPUT "Enter the height in inches: "; height$
    IF base$="" or height$="" THEN GOSUB [knucklehead] : GOTO [triangle]
    base=VAL(base$)
    height=VAL(height$)
    'If the user is messing with our mind, give him the Knudkle Head Prize!
    IF base <= 0 OR height <= 0 THEN GOSUB [knucklehead] : GOTO [triangle]
    GOSUB [calTriangle]  'No need to pass variables to a GOSUB
    PRINT "The area of the triangle is "; area; " sq/inches."

    CASE "Q"
    GOTO [quit]  'Exit the program after 'Goodbye' message.

    CASE ELSE
    PRINT "My apologies, sir.  Your response did"+ CHR$(13)+ _
    "not match any of my selections."
    TIMER 2500, [doDemo]
    WAIT  'Wait for the TIMER event.
    END SELECT

PRINT
INPUT "Do again (Y/N)? "; resp$
[quit]
IF LEFT$(resp$,1)="Y" OR  LEFT$(resp$,1)="y" GOTO [doDemo] _
ELSE PRINT "Okay, have a nice day!"+ CHR$(13) + _
"Come back to keep me company again."
TIMER 2000, [close]
WAIT  'Wait for the TIMER event.

[close]
CLS  'End with a clear screen.
END

'Subs, Subroutines, Functions, and error notice below here.
[calTriangle]  'Calculate the area of a triangle using a sub-routine.
    area=(base*height)/2
RETURN

FUNCTION sqcir(alias)  'Return a value using FUNCTION
    sqcir=(3.14159*alias^2)  'Do the calculation
END FUNCTION

SUB doSquare byref alias  'byref' returns the value of "alias" to the program.
    alias=(alias^2)
END SUB

[knucklehead]
    NOTICE "Knucklehead Response"+CHR$(13)+ _
    "You did not enter a valid "+CHR$(13)+ _
    "measurement.  Try again!"
RETURN
 


Before variables from the main program can be used in a FUNCTION or SUB, they must be passed to that portion of code. By default, JB passes variables by value, which allows the routine to 'do something' while the variable in the main program remains unchanged. If, however, we intend to change the value in the main program, we pass it 'byref' and a new value will be assigned to the variable in the main program when execution returns, as in the SUB doSquare, above.

The first routine calculates the area of a circle when the user enters the radius into the program. We get the radius as a string variable, then convert it to a number using the VAL() function. Why do we do this? Have you ever watched America's Funniest Videos? People do strange things, either by accident or intent. Accepting a string value allows us several methods to check for errors, regardless of input. Here we check for a valid response and to see if any input at all was entered. If there was none, the program branches to a GOSUB and the user is awarded the Knucklehead Prize. Execution then returns to the main program and the user is allowed to try again. We also tested for negative values, just to see if the user was jerking our chain.

If the user entered an acceptable value it is passed to a user designed function, mathematics is performed, and the result is returned to the main program. JB provides numerous built-in functions, but if you need to create one yourself you can do so. In this demo, the function to calculate the area of a circle is named "sqcir" and the value passed is "rad" because this is really a "rad" concept. I like to put all my subs, GOSUBS and FUNCTIONS following the END statement in a program, so skip down to the FUNCTION statement for the example.

Notice when we left the [circle] block of code, we passed a variable named "rad", but in the function statement it is named "alias." This is permissible, and even useful in the event we have a FUNCTION call from elsewhere in the program and the variable has a different name. Perhaps the user is somewhere in the Constellation Orion and the name is "glipptrisk"? The FUNCTION will work anyway using the value entered as resp$.

Functions must end with the END FUNCTION command. After the FUNCTION has done it's work, control returns to the next line in the demo and the result is printed using PRINT sqcir(rad). Text can be appended to the result to make it more meaningful when displayed. FUNCTIONS are useful in the event we must do something repeatedly, using a method or procedure which could not be anticipated or included by the creators of the programming language.

Then next block of code calculates the area of a square using a SUB routine. The statement to do something with a sub-routine is CALL label, in this case, CALL doSquare. The resulting answer is passed "byref" and can be 'seen,' by the main program, as well as changed by the sub-routine. If we do not want the value changed in the main program, we allow it to be passed "by value," which is the default unless JB is told otherwise. A sub-routine must have an END SUB command.

The last method in the demo is a GOSUB. All variables in the main program can be used by the GOSUB, vice-versa, any variables changed in the GOSUB will affect the values used in the main program. Because of this GLOBAL scope, it is not necessary to pass variables to a GOSUB.

The block to calculate the area of a triangle gets two inputs from the user, checks for valid input, then branches to GOSUB [calTriangle] where the area is calulated. Execution returns to the line following the GOSUB command and the result is printed.

In this demonstration code, a GOSUB was used for the error notice, because a SUB or FUNCTION cannot branch elsewhere in the program to print the selected error response. After the user has been notified of his faux-pas, we want to give him another chance to enter a response the program can use.

We attempted to anticipate common errors by the user and avoid needless program crashes. No one can anticipate every possible error or mistake, which is one reason "America's Funniest Videos" is such a popular TV show. Multiple errors could be compared using a SELECT CASE block of code and branch to different error responses, perhaps [knucklehead2] or [heyUdummy]. You're the coder and you can write the code as you prefer. Error messages should be informative so the user will know what he/she did wrong and can try again, but not too rude. Perhaps the mistake was in the way the coder evaluated the response which triggered the error message? I know it's hard to believe, but even good coders
« Last Edit: Apr 8th, 2011, 02:45am by Stefan Pendl » User IP Logged

JB 1.01
Win7 64bit, 4 GB RAM, Pentium 6200@2.13 GHz (laptop)
WinXP, 1 GB RAM, Intel N270@1.6 GHz (netbook)
Stefan Pendl
Administrator
ImageImageImageImageImage


member is offline

Avatar

Let's talk JB ...


Homepage PM

Gender: Male
Posts: 3712
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #1 on: Apr 8th, 2011, 02:48am »

Direct links to the articles:

User IP Logged

Stefan - Homepage

Remember to read the forum rules board wink

Just BASIC 1.01, Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
tooanalytical
Senior Member
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1739
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #2 on: Apr 9th, 2011, 12:00am »

Let me ask if I understand the ByRef article:

Usisng ByRef is like using the GLOBAL command when calling a function by value?
User IP Logged

Stefan Pendl
Administrator
ImageImageImageImageImage


member is offline

Avatar

Let's talk JB ...


Homepage PM

Gender: Male
Posts: 3712
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #3 on: Apr 9th, 2011, 02:40am »

on Apr 9th, 2011, 12:00am, tooanalytical wrote:
Usisng ByRef is like using the GLOBAL command when calling a function by value?


Not exactly, but close.

A global variable is called the same in the whole program, whereas ByRef allows one to get variable A from outside the procedure inherit the value of variable X from inside the procedure.

Generally global variables defeat the purpose of reusable procedures, since they are global in scope and add a dependency to code outside of the procedure.

ByRef allows to keep the procedure independent from code outside of it, which follows the rules for independent reusable code.
User IP Logged

Stefan - Homepage

Remember to read the forum rules board wink

Just BASIC 1.01, Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
Stefan Pendl
Administrator
ImageImageImageImageImage


member is offline

Avatar

Let's talk JB ...


Homepage PM

Gender: Male
Posts: 3712
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #4 on: Apr 9th, 2011, 02:47am »

Global Variable Code:
Global GlobalVar

Print GlobalVar

Call Increment

Print GlobalVar

End

Sub Increment
    GlobalVar = GlobalVar + 1
End Sub
 


Versus ByRef Code:
Print MainVar

Call Increment MainVar

Print MainVar

End

Sub Increment ByRef LocalVar
    LocalVar = LocalVar + 1
End Sub
 
« Last Edit: Apr 9th, 2011, 02:47am by Stefan Pendl » User IP Logged

Stefan - Homepage

Remember to read the forum rules board wink

Just BASIC 1.01, Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
TyCamden
Global Moderator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1431
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #5 on: Apr 9th, 2011, 11:39am »

on Apr 9th, 2011, 02:47am, Stefan Pendl wrote:
( two code examples )


Just a quick comment on his examples.

I believe the ByRef example (the second one) is a better way to handle things, because you could use that sub for other variables.

For example...

Code:
Print "MainVar = "; MainVar
Print "(incrementing)" : Call Increment MainVar
Print "MainVar = "; MainVar

Print

Print "SecondVar = "; SecondVar
Print "(incrementing)" : Call Increment SecondVar
Print "MainVar = "; MainVar
Print "SecondVar = "; SecondVar

End

Sub Increment ByRef LocalVar
    LocalVar = LocalVar + 1
End Sub 

User IP Logged

TyCamden

Please give credit if you use code I post, no need to ask for permission.


Just BASIC 1.01, Windows 7 Home Premium version (2009), AMD Athelon II 320 Dual-Core Processor 2.10 GHz - 4.00 GB RAM (3.75 usable) - 64-bit OS
Stefan Pendl
Administrator
ImageImageImageImageImage


member is offline

Avatar

Let's talk JB ...


Homepage PM

Gender: Male
Posts: 3712
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #6 on: Apr 9th, 2011, 1:40pm »

on Apr 9th, 2011, 11:39am, TyCamden wrote:
I believe the ByRef example (the second one) is a better way to handle things, because you could use that sub for other variables.


Yes, that is exactly what I wanted to describe.

Having a global variable will limit the re-usability of the procedure, whereas ByRef allows the procedure to be used in many cases.
User IP Logged

Stefan - Homepage

Remember to read the forum rules board wink

Just BASIC 1.01, Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
tooanalytical
Senior Member
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1739
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #7 on: Apr 9th, 2011, 8:51pm »

This was difficult to understand at first, and understanding it required several minutes of thought.

on Apr 9th, 2011, 1:40pm, Stefan Pendl wrote:
Yes, that is exactly what I wanted to describe.

Having a global variable will limit the re-usability of the procedure, whereas ByRef allows the procedure to be used in many cases.
User IP Logged

jaba
Global Moderator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1049
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #8 on: Apr 9th, 2011, 9:18pm »

I think the problem is the terms by value and byref.

I propose we storm the offices of Shoptalk Systems, take Carl hostage, and force him to rename these terms.

So, the question is: What should we name them? wink
User IP Logged

JACK - Windows 8.1 64-bit; 2.5 GHz Intel i3 processor; 6.00 GB RAM;
Stefan Pendl
Administrator
ImageImageImageImageImage


member is offline

Avatar

Let's talk JB ...


Homepage PM

Gender: Male
Posts: 3712
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #9 on: Apr 10th, 2011, 09:17am »

ByRef (by reference) and ByVal (by value) are widely used terms in the programming world, so there will be no better word to find.

ByRef passes along the memory address of the variable, which allows the procedure to change the contents of the variable directly.

ByVal (the default) passes along only the contents of a variable, which will be stored in a local variable of the procedure.
User IP Logged

Stefan - Homepage

Remember to read the forum rules board wink

Just BASIC 1.01, Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
jaba
Global Moderator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1049
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #10 on: Apr 13th, 2011, 10:39pm »

on Apr 10th, 2011, 09:17am, Stefan Pendl wrote:
ByRef (by reference) and ByVal (by value) are widely used terms in the programming world, so there will be no better word to find.

ByRef passes along the memory address of the variable, which allows the procedure to change the contents of the variable directly.

ByVal (the default) passes along only the contents of a variable, which will be stored in a local variable of the procedure.

Well, there ya go! How about: byCon for contents, and byMem for memory address?

My tongue is only partly in my cheek. wink
User IP Logged

JACK - Windows 8.1 64-bit; 2.5 GHz Intel i3 processor; 6.00 GB RAM;
tsh73
JB-Supporter


member is offline

Avatar




PM

Gender: Male
Posts: 3636
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #11 on: Apr 14th, 2011, 04:11am »

Quote:
ByRef (by reference) and ByVal (by value) are widely used terms in the programming world


so all programmers instantly understand what you mean.

Really, inventing your own terms just will not pay.
User IP Logged

Q: "And if I took your codes and compile them, and sell them for a profit"?
A: Go ahead. I had my share of good then I coded it for fun, if you can make better use of it - please do.
(enjoying JB 1.01 on WinXP, netbook and desktop)
jaba
Global Moderator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1049
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #12 on: Apr 14th, 2011, 05:59am »

on Apr 14th, 2011, 04:11am, tsh73 wrote:
so all programmers instantly understand what you mean.

Really, inventing your own terms just will not pay.


tsh73,

My apologies. The phrase "tongue in cheek" is an American saying meaning "jokingly". I'll be more thoughtful in the future. Thanks for pointing this out.

jaba
User IP Logged

JACK - Windows 8.1 64-bit; 2.5 GHz Intel i3 processor; 6.00 GB RAM;
pantsonfire
Member in Training
ImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 25
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #13 on: Aug 10th, 2011, 4:39pm »

On the subject of Functions may i use this space to ask a question. Say i have 2 arrays x(20),y(20) for example. How do i write a function to sum the array values and for the function to be able to distinguish the individual arrays. I suppose what i am trying to say, is it posible to pass my array as a parameter.
User IP Logged

Welopez
Moderator
ImageImageImageImageImage


member is offline

Avatar

Never let your beliefs get in the way of learning.


PM

Gender: Male
Posts: 4407
xx Re: SUB, GOSUB, FUNCTION, Useful ERROR Messages
« Reply #14 on: Aug 10th, 2011, 5:19pm »

Hold your pants on, buddy! Why do you need to pass an array value? Didn't anyone tell you arrays are global in scope?

Once you have filled your arrays, you can use:
PRINT "Sum = "; x(n)+y(m)
... anywhere in your program, where n and m are the subcategories of x and y. Got it?

Good luck to you!
User IP Logged

JB 1.01
Win7 64bit, 4 GB RAM, Pentium 6200@2.13 GHz (laptop)
WinXP, 1 GB RAM, Intel N270@1.6 GHz (netbook)
Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

Conforums Terms of Service | Membership Rules | Home | Search | Recent Posts | Notification | Format Your Message | Installation FAQ

Donate $6.99 for 50,000 Ad-Free Pageviews!

| |

This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls