Recent

Author Topic: Remove goto from procedure  (Read 5723 times)

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Remove goto from procedure
« Reply #30 on: February 09, 2024, 03:32:38 pm »
I‘m not denying there possibly being situations that justify Goto, but I haven’t come across them

Referring to linux kernel cited page:

Quote
[...]

The rationale for using gotos is:

  • unconditional statements are easier to understand and follow
  • nesting is reduced
  • errors by not updating individual exit points when making modifications are prevented
  • saves the compiler work to optimize redundant code away ;)
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

440bx

  • Hero Member
  • *****
  • Posts: 4908
Re: Remove goto from procedure
« Reply #31 on: February 09, 2024, 03:54:07 pm »
About the above rationales for using gotos...

I see _all_ of those as attempts to rationalize poorly designed code that the programmers are either too lazy to improve or simply not capable of figuring out how to do _correctly_.

a few more rationales...

War is good because it helps control population and, it's good to keep older people employed too (because the young and physically strong got shot in the war.)  see ??... war is good stuff.

Even manure is good stuff... it's a primordial ingredient in fertilizer and, absent "population control" (read "war") fertilizer is very important (the young and strong eat more than the old and weak.)

The point ?...  just about anything can be rationalized... doesn't make it right or desirable.

To be fair, gotos have a plus over other "programming techniques", that is, at least the goto is explicit, not hidden in some cool sounding language construct.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Remove goto from procedure
« Reply #32 on: February 09, 2024, 04:08:26 pm »
I see _all_ of those as attempts to rationalize poorly designed code that the programmers are either too lazy to improve or simply not capable of figuring out how to do _correctly_.

Well, linux kernel programmers seem to me difficult to categorize like that.

Anyway, all these are opinions. And if uncond jumps were so bad, prob they were banned from the programming languages, but this is not the case, not only with fpc.
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Curt Carpenter

  • Hero Member
  • *****
  • Posts: 578
Re: Remove goto from procedure
« Reply #33 on: February 09, 2024, 04:39:15 pm »
... https://www.kernel.org/doc/html/v4.19/process/coding-style.html#centralized-exiting-of-functions

That's a good example.  A single label reached from multiple goto statements in a complex procedure really can, in my view, make it more readable, and that ranks high in my list of priorities.  The benefit decays exponentially as the number of labels gets greater than one though.

"Used very judiciously" (maybe "no more than label per function or procedure") would seem better than "never never never."

Zvoni

  • Hero Member
  • *****
  • Posts: 2800
Re: Remove goto from procedure
« Reply #34 on: February 09, 2024, 04:42:25 pm »
That said: while porting C-Code to pascal, and encountering a Goto for premature exit (with Cleanup) i could always solve it with a nested boolean-function, doing cleanup, that always returns true.

Why do you use function that always returns true?

Why not like that (procedure instead of function):
Code: Pascal  [Select][+][-]
  1. If SomeErrorCondition Then
  2. begin
  3.   CleanUp(SomeArgument);
  4.   Exit;
  5. end;
Because i‘m a lazy bugger, and i try to avoid „unnecessary“ Begin/End blocks  :D :D
And in case i have to change the cleanup-code, and something goes wrong there, i can catch it with my Boolean function, if i change „always true“ to a real Boolean result
It‘s just an optional backdoor i leave in my code
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Remove goto from procedure
« Reply #35 on: February 09, 2024, 04:53:26 pm »
"Used very judiciously" [...] would seem better than "never never never."

I strongly agree with this way of thinking.
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1296
Re: Remove goto from procedure
« Reply #36 on: February 27, 2024, 01:22:41 pm »
Code: Pascal  [Select][+][-]
  1. procedure hqr(var a:TArray2D;n:integer;var wr,wi: TArray1D);
  2. label 2,3,4;
  3. var
  4.    nn,m,l,k,j,its,i,mmin:integer;
  5.    z,y,x,w,v,u,t,s,r,q,p,anorm:TElem;
  6. begin
  7.    anorm := abs(a[1,1]);
  8.    for i := 2 to n do
  9.        for j := i-1 to n do
  10.           anorm := anorm + abs(a[i,j]);
  11.           nn := n;
  12.           t := 0;
  13.           while nn >= 1 do
  14.           begin
  15.             its := 0;
  16.        2:   for l := nn downto 2 do
  17.             begin
  18.               s:= abs(a[l-1,l-1])+abs(a[l,l]);
  19.               if s = 0.0 then
  20.                  s := anorm;
  21.               if abs(a[l,l-1])+s = s then
  22.                   goto 3
  23.             end;
  24.             l := 1;
  25.        3:   x := a[nn,nn];
  26.        if l = nn then
  27.        begin
  28.          wr[nn] := x + t;
  29.          wi[nn] := 0.0;
  30.          nn := nn-1
  31.        end
  32.        else
  33.        begin
  34.           y := a[nn-1,nn-1];
  35.           w := a[nn,nn-1]*a[nn-1,nn];
  36.           if l = nn-1 then
  37.           begin
  38.             p := 0.5*(y-x);
  39.             q := sqr(p)+w;
  40.             z := sqrt(abs(q));
  41.             x := x + t;
  42.             if q >= 0.0 then
  43.             begin
  44.               z := p + sign(z,p);
  45.               wr[nn] := x + z;
  46.               wr[nn-1] := wr[nn];
  47.               if z <> 0.0 then
  48.                  wr[nn] := x - w/z;
  49.                  wi[nn] := 0.0;
  50.                  wi[nn] := 0.0
  51.                end  
  52.                else
  53.                begin
  54.                  wr[nn] := x + p;
  55.                  wr[nn-1] := wr[nn];
  56.                  wi[nn] := z;
  57.                  wi[nn-1] := -z
  58.                end;
  59.                nn := nn-2
  60.              end
  61.              else
  62.              begin
  63.                if its = 30 then
  64.                begin
  65.                  writeln('pause in routine HQR');
  66.                  writeln('too many iterations') ;
  67.                  readln;
  68.                end;
  69.                if (its = 10) or (its = 20) then
  70.                begin
  71.                  t := t + x;
  72.                  for i := 1 to nn do
  73.                      a[i,i] := a[i,i] - x;
  74.                  s := abs(a[nn,nn-1])+abs(a[nn-1,nn-2]);
  75.                  x := 0.75*s;
  76.                  y := x;
  77.                  w := -0.4375*sqr(s)
  78.                end;
  79.                its := its + 1;
  80.                for m := nn-2 downto l do
  81.                begin
  82.                  z := a[m,m];
  83.                  r := x - z;
  84.                  s := y - z;
  85.                  p := (r*s-w)/a[m+1,m]+a[m,m+1];
  86.                  q := a[m+1,m+1] - z - r - s;
  87.                  r := a[m+2,m+1];
  88.                  s := abs(p) + abs(q) + abs(r);
  89.                  p := p/s;
  90.                  q := q/s;
  91.                  r := r/s;
  92.                  if m = l then goto 4;
  93.                  u := abs(a[m,m-1])*(abs(q)+abs(r));
  94.                  v := abs(p) * (abs(a[m-1,m-1]) + abs(z) + abs(a[m+1,m+1]));
  95.                  if u+v = v then goto 4
  96.                end;
  97.            4:  for i := m+2 to nn do
  98.                begin
  99.                  a[i,i-2] := 0;
  100.                  if i <> m+2 then
  101.                     a[i,i-3] := 0.0
  102.                end;
  103.                for k := m to nn-1 do
  104.                begin
  105.                  if k <> m then
  106.                  begin
  107.                      p := a[k,k-1];
  108.                      q := a[k+1,k-1];
  109.                      if k <> nn-1 then
  110.                         r := a[k+2,k-1]
  111.                      else
  112.                         r := 0.0;
  113.                      x := abs(p) + abs(q) + abs(r);
  114.                      if x <> 0.0 then
  115.                      begin
  116.                        p := p/x;
  117.                        q := q/x;
  118.                        r := r/x;
  119.                      end
  120.                   end;
  121.                   s := sign(sqrt(sqr(p) + sqr(q) + sqr(r)),p);
  122.                   if s <> 0.0 then
  123.                   begin
  124.                     if k = m then
  125.                     begin
  126.                       if l <> m then
  127.                         a[k,k-1] := -a[k,k-1];
  128.                       end
  129.                       else
  130.                          a[k,k-1] := -s*x;
  131.                       p := p+s;
  132.                       x := p/s;
  133.                       y := q/s;
  134.                       z := r/s;
  135.                       q := q/p;
  136.                       r := r/p;
  137.                       for j := k to nn do
  138.                       begin
  139.                         p := a[k,j]+q*a[k+1,j];
  140.                         if k <> nn-1 then
  141.                         begin
  142.                           p := p + r * a[k+2,j];
  143.                           a[k+2,j] := a[k+2,j] - p*z
  144.                         end;
  145.                         a[k+1,j] := a[k+1,j]   - p*y;
  146.                         a[k,j] := a[k,j] -p*x
  147.                       end;
  148.                       mmin := min(nn,k+3);
  149.                       for i := l to mmin do
  150.                       begin
  151.                         p := x * a[i,k]+y*a[i,k+1];
  152.                         if k <> nn-1 then
  153.                         begin
  154.                           p := p + z *a[i,k+2];
  155.                           a[i,k+2] := a[i,k+2] - p*r
  156.                         end;
  157.                         a[i,k+1] := a[i,k+1] - p*q;
  158.                         a[i,k] := a[i,k] - p
  159.                       end
  160.                     end
  161.                   end;
  162.                   goto 2
  163.                 end
  164.               end
  165.             end    
  166. end;
  167.  

I found this procedure in Numerical recipes in Pascal
(Press , Teukolsky and others)
and I would like to remove labels

I tried to replace  labels  myself by
modyfing loops and introducing some boolean variables
 I received behavior similar to infinite loop
after playing with these labels

Since this isn’t marked solved yet I figured I would share how I would solve it.
I would copy the code and comment it out and then start modifying it.
First I Would move the labeled code inside procedure2, procedure3 etc
The gotos would be replaced with procedure calls.
After that it would be easier to tidy up the code I think.

The variables don’t have meaningful names and seem to be reused for unrelated things..
That needs fixing as well.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

Zvoni

  • Hero Member
  • *****
  • Posts: 2800
Re: Remove goto from procedure
« Reply #37 on: February 27, 2024, 02:04:00 pm »
Since this isn’t marked solved yet I figured I would share how I would solve it.
I would copy the code and comment it out and then start modifying it.
First I Would move the labeled code inside procedure2, procedure3 etc
The gotos would be replaced with procedure calls.
After that it would be easier to tidy up the code I think.

The variables don’t have meaningful names and seem to be reused for unrelated things..
That needs fixing as well.
Wrong.
The solution is to NOT copy/paste some code from the internet (or from wherever else) WITHOUT understanding what it does.
And if that "c&p"-ed code doesn't do what it's advertised to do, then first check, if you actually have the "original".
Because if not, hunt down the "original". And the "original" in this case wasn't the pascal-version, but the c-version

That's what i did. And i found the original c-code. And i ported it to pascal.
And i didn't have to use a single label/goto there
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1296
Re: Remove goto from procedure
« Reply #38 on: February 27, 2024, 02:41:07 pm »
Ah I thought the exercise was to remove the gotos from code provided.

 The code presented is so confusing that my first urge was to simply it.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Remove goto from procedure
« Reply #39 on: February 28, 2024, 08:42:18 am »
Because if not, hunt down the "original". And the "original" in this case wasn't the pascal-version, but the c-version

That's what i did. And i found the original c-code. And i ported it to pascal.
And i didn't have to use a single label/goto there

No, the original for this pascal code is Fortran 77 code with its gotos and labels, and this pascal code follows it almost verbatim.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8138
Re: Remove goto from procedure
« Reply #40 on: February 28, 2024, 09:04:20 am »
No, the original for this pascal code is Fortran 77 code with its gotos and labels, and this pascal code follows it almost verbatim.

And that FORTRAN-77 code possibly represents an algorithm well-known to specialists in the field, with well-understood numerical behaviour.

It is not something to be rearranged casually.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Zvoni

  • Hero Member
  • *****
  • Posts: 2800
Re: Remove goto from procedure
« Reply #41 on: February 28, 2024, 09:09:16 am »
Because if not, hunt down the "original". And the "original" in this case wasn't the pascal-version, but the c-version

That's what i did. And i found the original c-code. And i ported it to pascal.
And i didn't have to use a single label/goto there

No, the original for this pascal code is Fortran 77 code with its gotos and labels, and this pascal code follows it almost verbatim.

OK, i'll take your word for it, since i only found a PDF with C-Source-code, which the PDF apparently was something like a "handout" for a students lecture
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Remove goto from procedure
« Reply #42 on: February 28, 2024, 10:06:23 am »
OK, i'll take your word for it, since i only found a PDF with C-Source-code, which the PDF apparently was something like a "handout" for a students lecture

http://s3.amazonaws.com/nrbook.com/book_F210.html Chapter 11. Eigensystems page 484

Dzandaa

  • Sr. Member
  • ****
  • Posts: 404
  • From C# to Lazarus
Re: Remove goto from procedure
« Reply #43 on: March 04, 2024, 10:19:03 am »
Hi,

Look at this code:

https://github.com/saulwiggin/Numerical-Recipies-in-C/blob/master/Chapter11.Eigensystems/hqr.c

It's written in C, but seems the same as yours without goto.

B->
Regards,
Dzandaa

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1296
Re: Remove goto from procedure
« Reply #44 on: March 04, 2024, 12:32:44 pm »
Hi,

Look at this code:

https://github.com/saulwiggin/Numerical-Recipies-in-C/blob/master/Chapter11.Eigensystems/hqr.c

It's written in C, but seems the same as yours without goto.

B->

I think the original poster got bored and left almost a month ago  :o
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

 

TinyPortal © 2005-2018