Author |
Topic: about GOSUBs (Read 1498 times) |
|
tsh73
Full Member
member is offline
Gender:
Posts: 210
|
|
about GOSUBs
« Thread started on: Jun 7th, 2016, 7:18pm » |
|
They are came up as a side-topic in reply 55 at this thread Card graphics not sticking And I thought matter is rested. But alas today I saw this on LB forum: Quote:Kind regards and may all your Gosubs Return |
|
so. If anything this is a "redeeming feature" for me.
May the Source be with you! ))
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #1 on: Jun 7th, 2016, 9:36pm » |
|
on Jun 7th, 2016, 7:18pm, tsh73 wrote:But alas today I saw this on LB forum: "Kind regards and may all your Gosubs Return" |
|
I can't see that comment (probably in a part of the forum I'm not allowed to read) but if it was a signature I don't think it is necessarily recommending the use of GOSUBs, but rather that if you do use them you'd better hope that they RETURN eventually!
Actually there's a serious point here. If, for example due to a convoluted program, the GOSUB never RETURNs (maybe it ends up at a WAIT) the result will be a memory leak that eventually, if the program is left running for long enough, will cause all the memory to be exhausted and a catastrophic failure.
If you use CALL rather than GOSUB it's less likely that a problem of this sort would go unnoticed, if only because you have to think more carefully about program structure.
Richard.
|
|
|
|
Mystic
Junior Member
member is offline
Gender:
Posts: 53
|
|
Re: about GOSUBs
« Reply #2 on: Jun 7th, 2016, 10:05pm » |
|
WOW! After reading that I feel like an idiot.
My programs are all about the GOSUBs. Throwback from TRS80, C64, Amiga QBASIC days I guess. LOL
Time to research more on CALLS and get my programming shit together I guess.
|
« Last Edit: Jun 7th, 2016, 11:24pm by Mystic » |
Logged
|
- Rick
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #3 on: Jun 8th, 2016, 08:22am » |
|
Here's an example of the sort of thing that can happen by accident. Try running the program in the LBB debugger and watch the 'Stack usage' figure:
Code: timer 10, [tick]
wait
[tick]
gosub [handler]
wait
[handler]
' do something
wait Of course with such a small program the problem is obvious, but in a large or convoluted program it could easily go unnoticed.
If I run that same program in the LB 4.04 debugger it doesn't give me any indication that anything is wrong.
Richard.
|
|
Logged
|
|
|
|
Mystic
Junior Member
member is offline
Gender:
Posts: 53
|
|
Re: about GOSUBs
« Reply #4 on: Jun 9th, 2016, 3:55pm » |
|
I've now removed all GOSUBS from one of my main programs, and replaced them with SUB's or FUNCTION's as needed.
I have two more larger ones to tackle. From now on I will tread lightly around the GOSUB and use these alternatives.
Apparently an old dog CAN learn new tricks!
Thanks Richard!
|
|
Logged
|
- Rick
|
|
|
RobM
Junior Member
member is offline
Posts: 91
|
|
Re: about GOSUBs
« Reply #5 on: Jun 9th, 2016, 8:02pm » |
|
Just ran the following program on my cabinet program. I have 9,198 gosub commands. :o
I seem to remember a discussion about the speed of gosubs, subs and functions back when I started with LB. Carl said gosubs were faster in general because subs & functions need to allocate memory each time they were used, whereas gosubs do not. Wonder if the same is true in LBB?
Code: filedialog "Open text file", "*.bas", fileName$
open fileName$ for input as #1
while not(eof(#1))
line input #1, temp$
if instr(temp$,"gosub")>0 then count=count+1
wend
print count
close #1
end
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #6 on: Jun 9th, 2016, 9:41pm » |
|
on Jun 9th, 2016, 8:02pm, RobM wrote:I seem to remember a discussion about the speed of gosubs, subs and functions back when I started with LB. Carl said gosubs were faster in general because subs & functions need to allocate memory each time they were used, whereas gosubs do not. Wonder if the same is true in LBB? |
|
It's not difficult to do the test. Here is the program I used:
Code: t0 = time$("ms")
for i = 1 to 200000
next
t1 = time$("ms")
for i = 1 to 200000
gosub [MySub]
next
t2 = time$("ms")
for i = 1 to 200000
call MySub
next
t3 = time$("ms")
print "Total time taken for GOSUBs = "; (t2 - t1) - (t1 - t0) ; " ms"
print "Total time taken for CALLs = "; (t3 - t2) - (t1 - t0) ; " ms"
end
[MySub]
return
sub MySub
end sub Results on my PC:
LBB v3.05: Total time taken for GOSUBs = 114 ms Total time taken for CALLs = 56 ms
LB v4.04: Total time taken for GOSUBs = 1328 ms Total time taken for CALLs = 4232 ms
So in LBB CALL is roughly twice as fast as GOSUB, and LBB's CALL is about seventy-five times faster than LB's CALL!
But of course the benefit will be much reduced once the subroutines actually contain some useful code. Also, it's arguably unfair not to pass any parameters to the SUB; passing just a single parameter makes CALL slower than GOSUB.
In most practical cases I would expect the time taken by the code within the subroutine to dominate the time taken in the actual GOSUB or CALL, so speed should not be an issue in deciding which to use.
Richard.
|
|
|
|
RobM
Junior Member
member is offline
Posts: 91
|
|
Re: about GOSUBs
« Reply #7 on: Jun 9th, 2016, 9:55pm » |
|
Similar results here.
LBB 3.03: Total time taken for GOSUBs = 35 ms Total time taken for CALLs = 13 ms
LB 4.04: Total time taken for GOSUBs = 546 ms Total time taken for CALLs = 1965 ms
|
« Last Edit: Jun 9th, 2016, 9:55pm by RobM » |
Logged
|
|
|
|
Jack Kelly
Full Member
member is offline
Gender:
Posts: 106
|
|
Re: about GOSUBs
« Reply #8 on: Aug 2nd, 2016, 09:46am » |
|
I've been looking at the code for Freeform 4. It contains about 68 gosub subroutines -- ones starting with a label and ending with a RETURN. 233 GOSUB calls are made to these subroutines. To convert all the gosubs to calls in this program would involve declaring possibly hundreds of global variables. Are there any downsides to global variables? Could this be a redeeming factor in using a GOSUB?
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #9 on: Aug 2nd, 2016, 1:05pm » |
|
on Aug 2nd, 2016, 09:46am, Jack Kelly wrote:Are there any downsides to global variables? Could this be a redeeming factor in using a GOSUB? |
|
The important question is: "what are those global variables used for?". With a traditional GOSUB..RETURN, global variables are the only way to pass values into a subroutine (inputs) or return values back from a subroutine (outputs). When replacing the GOSUB with a CALL any global variables used solely for those purposes should be substituted by the appropriate 'modern' equivalents: parameters for inputs and BYREF parameters (or the value returned from a FUNCTION) for outputs.
Having substituted the global variables used for inputs and outputs, any other global variables still accessed from within the subroutine will, as you say, have to be declared as GLOBAL. If the program is well structured, there should be relatively few such variables and they should be 'inherently' global in scope (i.e. making them GLOBAL should actually enhance the readability of the code rather than the opposite).
However if there are global variables accessed within the subroutine that are neither 'inputs', 'outputs' nor of genuinely 'global scope' then the program is poorly structured. You cannot convert a poorly structured program into a structured program just by replacing GOSUBs with CALLs, so in that case you should probably give up the struggle and declare the program to be beyond redemption!
Richard.
|
|
|
|
joker
Global Moderator
member is offline
Gender:
Posts: 157
|
|
Re: about GOSUBs
« Reply #10 on: Aug 2nd, 2016, 1:46pm » |
|
Oh Richard, your succinct replies are beyond reproach!
|
|
Logged
|
|
|
|
BrianM
New Member
member is offline
Posts: 15
|
|
Re: about GOSUBs
« Reply #11 on: Aug 2nd, 2016, 4:10pm » |
|
Gosubs are not completely redundant as they can be used inside subroutines and functions. The advantage in using a gosub over using a subroutine or function is that the gosub code "sees" the same variables as the calling sub or function and so no extra global variables are required to share data. The disadvantage is that you cannot use parameters. In certain situations this can result in a simpler code structure.
This is similar to internal and nested subroutines available in other languages.
I have found that in LBB that the labels for the gosub code must be unique throughout the program and not just in the enclosing subroutine or function. This is not the case in Liberty Basic.
Brian Matthews
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #12 on: Aug 2nd, 2016, 4:51pm » |
|
on Aug 2nd, 2016, 4:10pm, BrianM wrote:I have found that in LBB that the labels for the gosub code must be unique throughout the program and not just in the enclosing subroutine or function. This is not the case in Liberty Basic. |
|
That is not correct, in general, as the simple test program below demonstrates:
Code: gosub [label1]
call mysub
call anothersub
gosub [label1]
stop
[label1]
print "At [label1] in the main program"
return
sub mysub
gosub [label1]
exit sub
[label1]
print "At [label1] in sub mysub"
return
end sub
sub anothersub
gosub [label1]
exit sub
[label1]
print "At [label1] in sub anothersub"
return
end sub You can probably contrive a situation in which it won't work, for example by placing the destination for the outer GOSUB after rather than before the SUBs, but if you follow the recommendation to place all SUBs and FUNCTIONs at the end of the program that situation won't arise.
Richard.
|
|
|
|
BrianM
New Member
member is offline
Posts: 15
|
|
Re: about GOSUBs
« Reply #13 on: Aug 2nd, 2016, 5:07pm » |
|
This is my test program that works in LB but not LBB. I can't see an error. Code:
call mysub1
call mysub2
end
sub mysub1
for i = 1 to 5
gosub [internal_sub]
next
exit sub
[internal_sub]
print "internal sub(mysub1)",i
return
end sub
sub mysub2
for i = 1 to 5
gosub [internal_sub]
next
exit sub
[internal_sub]
print "internal sub(mysub2)",i
return
end sub
Brian Matthews
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline
Posts: 1348
|
|
Re: about GOSUBs
« Reply #14 on: Aug 2nd, 2016, 5:35pm » |
|
on Aug 2nd, 2016, 5:07pm, BrianM wrote:This is my test program that works in LB but not LBB. I can't see an error. |
|
That's a quite separate issue, caused by you including an 'illegal' character (an underscore) in your labels. This is what the LB Help File has to say about label names: "The label can be either a traditional line number or a branch label in the format [branchLabel] where the branch label name can be any upper/lowercase letter combination. Spaces and digits are not allowed".
It's not as precise as I would like, but I interpret "any upper/lowercase letter combination" as not permitting the use of an underscore - after all underscores definitely aren't allowed in variable names (except Windows Constants) and it's uncommon for different rules to apply.
If you remove the underscores from your label names (or substitute a character which is legal in a variable name like a dot) the program works as expected:
Code:call mysub1
call mysub2
end
sub mysub1
for i = 1 to 5
gosub [internalsub]
next
exit sub
[internalsub]
print "internal sub(mysub1)",i
return
end sub
sub mysub2
for i = 1 to 5
gosub [internalsub]
next
exit sub
[internalsub]
print "internal sub(mysub2)",i
return
end sub Richard.
|
|
Logged
|
|
|
|
|