Why OOP?

New to FreeBASIC? Post your questions here.
Linuxbob
Posts: 60
Joined: Sep 01, 2010 1:03
Location: Ohio, USA

Post by Linuxbob »

One of the 'nice' side effects of the FB style of OOP is that inheritance in most cases can be achieved by simply using the editor tools. Using the widget example, say in C++ you have:

class WIDGET {
...
}

For C++ inheritance one writes:

class WIDGET1: public WIDGET {
...
}

In FB one writes:

type WIDGET
...
end type

In FB, to achieve a measure of inheritance, one can just reuse the WIDGET UDT, rename it WIDGET1 and start adding the additional features that WIDGET1 needs. All of WIDGET is still there. Yes, there is a lot of duplication of code, but until inheritance is implemented in FB the goal of inheritance can at least be achieved. The UDT definitions can be kept in .bi files so their management is not quite so difficult. And honestly, IMHO doing inheritance this way makes it easier for one who is still learning the finer points of OOP.
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

Guess which one executes the fastest - using -lang FBlite. Run it a few times and you will see that even the timer doesn't know.

Code: Select all

TI!=timer   
Do
   A=A+1 
   Print "I am a Doof."
Loop until A = 10
print timer - TI!
A=0
TI!=Timer
100 PRINT "I AM A DOOF."
A=A+1 
if A=10 goto 210
200 GOTO 100
210 print timer - TI!
sleep
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Why OOP?

Post by MichaelW »

Your runtimes are almost entirely the execution time of the print statements. If I eliminate the print statements in the loops and increase the loop counts to 100000000, then running on my 500 MHz P3 the first loop is consistently faster, but not by much (<<1%). The problem with GOTO is not the speed - it’s the spaghetti.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Why OOP?

Post by marcov »

If sb is searching for a case where goto is faster, I would try to test if jumping out of nested IF statements is faster than letting the compiler take its course. so (in pseudo code)

Code: Select all

label 10;

if bla then
   if bla2 then
    dosomething1; 
    goto 10
   else
    dosomething2; 
   end if
else
     dosomething3;
end if 
10:
This kind of constructs is slightly faster in many compilers than the same code without the goto. This because it inserts one goto to replace two (the one to skip over the "else" part of the inner if, and the one to skip over the "else" part ofthe outer if)

If dosomething is the most used path in a deeply nested loop it can yield a small performance gain (more if deeper nested). I use it in a image analysis routine (that walks over pixels so is called millions of times per second)
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

It is only spaghetti if not used wisely. Same as some other non BASIC programming that I have seen. Spaghetti is not BASIC's fault it is the Programmers mess up with convoluted programs irrespective of the language they write in.
If all the other line numbers except those referenced by a GOSUB or GOTO are eliminated then it is easy to follow. With judicious use of REM's - i.e not over the wall craziness with a REM on just about every line then ten months later any program in any language is easier to follow than to work out what is what.
I've checked out some ASM code and boy are there jmp's (Which is the same as GOTO) I would say that even EXIT LOOP, or whatever is a disguised GOTO.

In the beginning the Goto runs faster and then the TIMER seems to get all mixed up and then the one and then the other runs faster. We cannot isolate print or throw it out; it is the reason for the loop.

But I only posted this to show that the TIMER 's head gets all screwed up.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Why OOP?

Post by dodicat »

Hi Theunis Jansen

Well that's a poke in the eye for all those goto snoots.
Goto has good advantages:
It's fast.

Unlike sub, function, gosub, asm call, it uses no stack.

For recursion, if goto can be used, then it should be used (my opinion).

I've altered my little prime factor thing into goto for fblite.

Code: Select all

rem PRIME FACTOR FINDER
#lang "fblite"
start:
Print "Numbers with their prime factors, choose your number limits (lower then upper)"
Print
Print "Enter your lower number (or 13 to quit)";
Input lowers%
If lowers%=13 Then End
Print "Enter your upper number (or 13 to quit)";
Input uppers%
If uppers%=13 Then End
Print "please wait "

For counts% = lowers% To uppers%
    number% = counts%
    Print number%;">>";
    divisor% = 2
    While divisor% <= number%
        Goto factor
        advance:
        divisor% = divisor% + 1
    Wend             
    Print
Next counts%
Print

Goto start
rem recursive Goto
factor:
If number% Mod divisor% = 0 Then
    Print divisor%;",";
    number% = number% \ divisor%
    Goto factor
    Endif
    Goto advance
    
    
       
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

Now that is the wise use of GOTO.
Just for some joke. I think ASM is the best programming language and BASIC is the easiest. So people laugh your heads off and dont kick this old man too hard. There isn't so much meat on my bones as ten years ago so you may get bone splinters in your foot.

OOP programming is good beyond all doubt and Is highly recommended, but even there, as in all things, one can get carried away.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Why OOP?

Post by marcov »

dodicat wrote:Hi Theunis Jansen

Well that's a poke in the eye for all those goto snoots.
Goto has good advantages:
It's fast.

Unlike sub, function, gosub, asm call, it uses no stack.
I'm not sure if that is true. Maybe in the current FB compiler, but it is certainly not a hard truth.
If you jump out of a block, and the block allocates stack space (e.g. temps for automated types,exception frames), the goto has to undo that before jumping out of it. Sometimes that can be avoided if the jump is to the end of the function, if the compiler is sophisticated enough.
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

@ Marcov
So what you are saying is it is a case of sometimes it is true and other times not, to which I agree. Hence my saying it must be used wisely (and also only when necessary.)
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Why OOP?

Post by marcov »

Theunis Jansen wrote:@ Marcov
So what you are saying is it is a case of sometimes it is true and other times not, to which I agree. Hence my saying it must be used wisely (and also only when necessary.)
No, I think it is always equal, except in the rare case I described earlier. (which in theory could also be achieved by a compiler setting).

So the overall statement is way more false than true.

It's the simplistic linear programming of your microbenchmarks that probably sets you off on the wrong path.and that can be done in a more procedural style too. (and in reality is, when programming for performance)
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

It is still a fact that many times it is not necessary to use a SUB or Function and in these and other cases where no stack space is involved it will execute faster, even if it is only micro- or milliseconds.

I am not advocating that GOTO be used indiscrimately. No what I keep saying is use it wisely. It is not a monster it is just a tool. That microbenchmark I used as an example is used quite a lot in some programs.
I know the attitude nowadays is "So what, we have terrabyte hard drives and multi core CPU's running at a few GHz so speed and space is no longer a problem".
Mihail_B
Posts: 273
Joined: Jan 29, 2008 11:20
Location: Romania
Contact:

Re: Why OOP?

Post by Mihail_B »

Here's a more precise benchmark for LOOP and GOTO.

The delay I entered between the 2 tests is to allow the sistem threads regarding to this program to finish.

By repeating the tests many time you will observe that sometimes LOOP is faster and sometimes GOTO is faster.

If you the compiler would have had used the proper optimizations there would've been no differences between the
statements.

At assembler level both GOTO/DO...LOOP implies jumping from one cpu instruction pointer to another.
There are faster and more optimim ways which can achive the shortest time duration for this kind of program that you are trying to benchmark.
:D

Code: Select all

sub rdtsc1(i as ulongint ptr)
	Asm
        push eax
        push edx
        push ecx
        rdtsc
        mov ecx,[i]
        mov [ecx],eax
        mov [ecx+4],edx
        pop ecx
        pop edx
        pop eax
	End asm
end Sub

Dim As ULongInt ti,tf,t_saved,t1,t2
Dim As Integer a
Dim As String c
restart01:
Sleep 500,1
a=0
rdtsc1(@ti)   
Do
   A=A+1 
   Print "I am a Doof."
Loop until A = 10
rdtsc1(@tf)
t_saved=tf-ti
print t_saved
Sleep 500,1
A=0
rdtsc1(@ti)
l100: A=A+1 
PRINT "I AM A DOOF."
if A=10 GoTo l210 
GOTO l100
l210: rdtsc1(@tf)
print tf-ti
Print "Tjump - Tloop=";clngint(tf-ti)-CLngInt(t_saved);
If CLngInt(tf-ti)-CLngInt(t_saved)<0 Then Print " => jump is faster " Else Print " => loop is faster"
Print "press any key to do another try or [ESC] to exit"
Sleep
c=InKey
If c=Chr(27) Then
   
   Cls
   Sleep 500,1
   rdtsc1(@t1)   
   Asm
      push ecx
      mov ecx,10
      .Lt_1111:
      push ecx
   End Asm
   Print "I am a Doof."
   Asm
      pop ecx
      Loop .Lt_1111 
      
      pop ecx
   End Asm
   rdtsc1(@t2)
   Print (t2-t1);" ";clngint(t2-t1)-CLngInt(t_saved);" ";clngint(t2-t1)-CLngInt(tf-ti)
   If  clngint(t2-t1)-CLngInt(t_saved)<0 Then Print "hand asm if faster the DO..LOOP"
   If  clngint(t2-t1)-CLngInt(tf-ti)<0 Then Print "hand asm if faster the GOTO"
   Line Input "press enter",c
   End
EndIf
Cls
GoTo restart01:


you can see the difference between LOOP and GOTO at assembler level :

Code: Select all

	.intel_syntax noprefix

	#jumplooptest.bas' compilation started at 10:36:41 (FreeBASIC 0.23.0)

.section .text
.balign 16

.globl _RDTSC1@4
_RDTSC1@4:
push ebp
mov ebp, esp
push ebx
push esi
push edi
.Lt_0004:
push eax
push edx
push ecx
rdtsc
mov ecx,[ebp+8]
mov [ecx],eax
mov [ecx+4],edx
pop ecx
pop edx
pop eax
.Lt_0005:
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 4
.balign 16

.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, 60
push ebx
push esi
push edi
mov dword ptr [ebp-4], 0
call ___main
push 0
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@12
.Lt_0002:
mov dword ptr [ebp-12], 0
mov dword ptr [ebp-8], 0
mov dword ptr [ebp-20], 0
mov dword ptr [ebp-16], 0
mov dword ptr [ebp-28], 0
mov dword ptr [ebp-24], 0
mov dword ptr [ebp-36], 0
mov dword ptr [ebp-32], 0
mov dword ptr [ebp-44], 0
mov dword ptr [ebp-40], 0
mov dword ptr [ebp-48], 0
mov dword ptr [ebp-60], 0
mov dword ptr [ebp-56], 0
mov dword ptr [ebp-52], 0
.Lt_0006:
push 1
push 500
call _fb_SleepEx@8
mov dword ptr [ebp-48], 0
lea eax, [ebp-12]
push eax
call _RDTSC1@4
.Lt_0007:
inc dword ptr [ebp-48]
push 1
push 12
push offset _Lt_000A
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
.Lt_0009:
cmp dword ptr [ebp-48], 10
jne .Lt_0007
.Lt_0008:
lea eax, [ebp-20]
push eax
call _RDTSC1@4
mov ebx, dword ptr [ebp-20]
mov eax, dword ptr [ebp-16]
sub ebx, dword ptr [ebp-12]
sbb eax, dword ptr [ebp-8]
mov dword ptr [ebp-28], ebx
mov dword ptr [ebp-24], eax
push 1
push dword ptr [ebp-24]
push dword ptr [ebp-28]
push 0
call _fb_PrintULongint@16
push 1
push 500
call _fb_SleepEx@8
mov dword ptr [ebp-48], 0
lea ebx, [ebp-12]
push ebx
call _RDTSC1@4
.Lt_000B:
inc dword ptr [ebp-48]
push 1
push 12
push offset _Lt_000C
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
cmp dword ptr [ebp-48], 10
jne .Lt_000E
jmp .Lt_000F
.Lt_000E:
jmp .Lt_000B
.Lt_000F:
lea eax, [ebp-20]
push eax
call _RDTSC1@4
push 1
mov ebx, dword ptr [ebp-20]
mov eax, dword ptr [ebp-16]
sub ebx, dword ptr [ebp-12]
sbb eax, dword ptr [ebp-8]
push eax
push ebx
push 0
call _fb_PrintULongint@16
push 0
push 14
push offset _Lt_0010
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
push 0
mov ebx, dword ptr [ebp-20]
mov eax, dword ptr [ebp-16]
sub ebx, dword ptr [ebp-12]
sbb eax, dword ptr [ebp-8]
mov esi, ebx
mov ecx, eax
sub esi, dword ptr [ebp-28]
sbb ecx, dword ptr [ebp-24]
push ecx
push esi
push 0
call _fb_PrintLongint@16
mov ecx, dword ptr [ebp-20]
mov esi, dword ptr [ebp-16]
sub ecx, dword ptr [ebp-12]
sbb esi, dword ptr [ebp-8]
mov eax, ecx
mov ebx, esi
sub eax, dword ptr [ebp-28]
sbb ebx, dword ptr [ebp-24]
cmp ebx, 0
jg .Lt_0012
jl .Lt_0021
cmp eax, 0
jae .Lt_0012
.Lt_0021:
push 1
push 19
push offset _Lt_0013
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
jmp .Lt_0011
.Lt_0012:
push 1
push 18
push offset _Lt_0014
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
.Lt_0011:
push 1
push 48
push offset _Lt_0015
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
push -1
call _fb_Sleep@4
push 0
push -1
call _fb_Inkey@0
push eax
push -1
lea eax, [ebp-60]
push eax
call _fb_StrAssign@20
push 2
push offset _Lt_0016
push -1
lea eax, [ebp-60]
push eax
call _fb_StrCompare@16
test eax, eax
jne .Lt_0018
push -65536
call _fb_Cls@4
push 1
push 500
call _fb_SleepEx@8
lea eax, [ebp-36]
push eax
call _RDTSC1@4
push ecx
mov ecx,10
.Lt_1111:
push ecx
push 1
push 12
push offset _Lt_000A
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
pop ecx
Loop .Lt_1111 
pop ecx
lea eax, [ebp-44]
push eax
call _RDTSC1@4
push 0
mov ebx, dword ptr [ebp-44]
mov eax, dword ptr [ebp-40]
sub ebx, dword ptr [ebp-36]
sbb eax, dword ptr [ebp-32]
push eax
push ebx
push 0
call _fb_PrintULongint@16
push 0
push 1
push offset _Lt_0019
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
push 0
mov ebx, dword ptr [ebp-44]
mov eax, dword ptr [ebp-40]
sub ebx, dword ptr [ebp-36]
sbb eax, dword ptr [ebp-32]
mov esi, ebx
mov ecx, eax
sub esi, dword ptr [ebp-28]
sbb ecx, dword ptr [ebp-24]
push ecx
push esi
push 0
call _fb_PrintLongint@16
push 0
push 1
push offset _Lt_0019
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
push 1
mov esi, dword ptr [ebp-44]
mov eax, dword ptr [ebp-40]
sub esi, dword ptr [ebp-36]
sbb eax, dword ptr [ebp-32]
mov ebx, esi
mov ecx, eax
mov eax, dword ptr [ebp-20]
mov esi, dword ptr [ebp-16]
sub eax, dword ptr [ebp-12]
sbb esi, dword ptr [ebp-8]
mov edx, eax
mov edi, esi
sub ebx, edx
sbb ecx, edi
push ecx
push ebx
push 0
call _fb_PrintLongint@16
mov ecx, dword ptr [ebp-44]
mov ebx, dword ptr [ebp-40]
sub ecx, dword ptr [ebp-36]
sbb ebx, dword ptr [ebp-32]
mov edi, ecx
mov edx, ebx
sub edi, dword ptr [ebp-28]
sbb edx, dword ptr [ebp-24]
cmp edx, 0
jg .Lt_001B
jl .Lt_0022
cmp edi, 0
jae .Lt_001B
.Lt_0022:
push 1
push 31
push offset _Lt_001C
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
.Lt_001B:
mov edi, dword ptr [ebp-44]
mov eax, dword ptr [ebp-40]
sub edi, dword ptr [ebp-36]
sbb eax, dword ptr [ebp-32]
mov ecx, edi
mov edx, eax
mov eax, dword ptr [ebp-20]
mov edi, dword ptr [ebp-16]
sub eax, dword ptr [ebp-12]
sbb edi, dword ptr [ebp-8]
mov esi, eax
mov ebx, edi
sub ecx, esi
sbb edx, ebx
cmp edx, 0
jg .Lt_001E
jl .Lt_0023
cmp ecx, 0
jae .Lt_001E
.Lt_0023:
push 1
push 27
push offset _Lt_001F
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
.Lt_001E:
push -1
push 0
push 0
push -1
lea eax, [ebp-60]
push eax
push 11
push offset _Lt_0020
call _fb_StrAllocTempDescZEx@8
push eax
call _fb_LineInput@24
push 0
call _fb_End@4
.Lt_0018:
.Lt_0017:
push -65536
call _fb_Cls@4
jmp .Lt_0006
lea eax, [ebp-60]
push eax
call _fb_StrDelete@4
.Lt_0003:
push 0
call _fb_End@4
mov eax, dword ptr [ebp-4]
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
	#jumplooptest.bas' compilation took 0.00407161258931632 secs

.section .data
.balign 4
_Lt_000A:	.ascii	"I am a Doof.\0"
.balign 4
_Lt_000C:	.ascii	"I AM A DOOF.\0"
.balign 4
_Lt_0010:	.ascii	"Tjump - Tloop=\0"
.balign 4
_Lt_0013:	.ascii	" => jump is faster \0"
.balign 4
_Lt_0014:	.ascii	" => loop is faster\0"
.balign 4
_Lt_0015:	.ascii	"press any key to do another try or [ESC] to exit\0"
.balign 4
_Lt_0016:	.ascii	"\33""\0"
.balign 4
_Lt_0019:	.ascii	" \0"
.balign 4
_Lt_001C:	.ascii	"hand asm if faster the DO..LOOP\0"
.balign 4
_Lt_001F:	.ascii	"hand asm if faster the GOTO\0"
.balign 4
_Lt_0020:	.ascii	"press enter\0"
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Why OOP?

Post by Theunis Jansen »

This has become quite interesting.
But I think so far everyone has actually missed the point which is that TIMER
is the culprit in the benchmark.
If you were to run the GOTO separately a number of times it will give different execution times and the same goes for the DO LOOP.
That is why I said the TIMER's head is all screwed up. which should have been the subject of the comments.
i.e why does TIMER act as it does by giving different times for the same thing. It does the same in QB4.5 as well as FB.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Why OOP?

Post by MichaelW »

Mihail_B wrote:Here's a more precise benchmark for LOOP and GOTO.
The print statements are so extremely slow that the values you are trying to compare, the loop and goto overheads, represent only an insignificant portion of the measured times, and that is why you see no significant difference in the timings. A demonstration:

Code: Select all

#lang "fblite"
'====================================================================
#include "windows.bi"
#include "counter.bas"
'====================================================================
'' Counter.bas is available here:
''
'' http://www.freebasic.net/forum/viewtopic.php?t=4221#4221
'====================================================================

dim as integer i

'------------------------------------------------------------------
'' This delay improves accuracy and repeatability by allowing time
'' for the system activities involved in launching an application,
'' disk cache activity for example, to finish so the test loop can
'' run with minimal interruptions.
'------------------------------------------------------------------

sleep 3000

counter_begin( 100, HIGH_PRIORITY_CLASS )
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
    print "I AM A DOOF."
counter_end
print counter_cycles;" cycles, print * 10"

counter_begin( 100, HIGH_PRIORITY_CLASS )
    i = 0
    do
        i += 1
    loop until i = 10
counter_end
print counter_cycles;" cycles, loop * 10"

counter_begin( 100, HIGH_PRIORITY_CLASS )
    i = 0
  100:
    i += 1
    if i < 10 goto 100
counter_end
print counter_cycles;" cycles, goto * 10"

sleep
Typical results running on a P3 processor:

Code: Select all

1893249 cycles, print * 10
71 cycles, loop * 10
78 cycles, goto * 10
To get an accurate comparison you need to eliminate the print statements.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Why OOP?

Post by marcov »

Theunis Jansen wrote:It is still a fact that many times it is not necessary to use a SUB or Function and in these and other cases where no stack space is involved it will execute faster, even if it is only micro- or milliseconds.
That is taste, not fact. Why? Because you _choose_ to limit your world around this one microscopic simplification and ignore everything else, and the "facts" that derive from that are useless since they are limited by the same microcosmos. I'll try to explain:

Nearly every program that does something is more likely to be bound by whatever form of memory management it uses then by this kind of micro optimizations. (the discussion code improvement optimalization vs algorithmic optimalization is a different discussion, for now I exclude algorithmic optimization beyond the common knowledge of a standard say CS bachelor graduate) Even performance requiring software is more sensitive to microoptimalization of datastructures. (utilizing cache effect, both alignment and size reduction paradoxically) then code microoptimalization.

One could consider that every second spent on such nonsense could be better spent elsewhere to resolve actual performance bottlenecks in actually used programs. Seen in that light, such indiscriminate micro optimalisations slow down your program. (since they eat up energy better spent elsewhere)

First rule of optimization: profile your _working_ program under as normal possible conditions, not some micro benchmark that extracts the one aspect of your programming style that you want to be confirmed. In that way your statement above is an opinion, not a fact
I am not advocating that GOTO be used indiscrimately. No what I keep saying is use it wisely. It is not a monster it is just a tool. That microbenchmark I used as an example is used quite a lot in some programs.
I know the attitude nowadays is "So what, we have terrabyte hard drives and multi core CPU's running at a few GHz so speed and space is no longer a problem".
It really rarely is useful outside of microbenchmarks. I used it 1 time (but then 3 goto's) outside my runtime library work in 10 years of programming. Half of which is an embedded and image recognition job. Those 3 goto's improved performance of a rate determining step by about 10%.

Is goto useless? We have had long discussions about this on the pascal lists years ago. The more interesting answers analysed cases like I describe above, and based on that justified goto use falls apart into three categories:

1 simplifying complex errorhandling in languages without exceptions.
2 cases like the above (see description with nested ifs in earlier mail), where goto can be used as a blunt tool to jump out of a nested construct.
3 In runtime libraries and other very low level libraries. Usually to defy procedural regimes in certain lowlevel operations (exception handlers, language helpers etc). Quite often in the implementation of the features that are meant to get rid of goto.

All three cases have arguments against it:
(1) Fix your language in some way to better structure complex error handling.
(2) Implement compiler pragma's to indicate to the compiler that code has certain "hot" paths and change the codegenerator/optimizer to optimize them.
(3) do the deepest plumbing in assembler or another language. (while that is shifting the problem, it does avoid ill advised use if you consider your language higher level than the level of goto. By that same redenation, if you have goto, you either have it for historic reasons or because you consider yourself to be a lowlevel (system) language.

There is no definitive answer if the contro arguments weigh up to their respective uses. That depends on project goals and investment levels (specially the fix to (2) can be expensive and never ending as users keep coming up with cases where improvement is possible. OTOH goto must also be engineered to work in all those cases)
Post Reply