Recent

Author Topic: FFS: step  (Read 3738 times)

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
FFS: step
« on: August 04, 2025, 01:57:02 pm »

for i := 0 to 100 step 5 do


PLEASE!!!!

Having to work around the lack of a 'step' in for loops is inelegant, inefficient and prone to error.
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: FFS: step
« Reply #1 on: August 04, 2025, 04:28:38 pm »
You could use enumerator:
Code: Pascal  [Select][+][-]
  1. {$MODESWITCH ADVANCEDRECORDS}
  2. {$MODE DELPHI}
  3.  
  4. type
  5.   TStepEnum<T> = record
  6.     I, Stop, Step: T;
  7.     function MoveNext: Boolean;
  8.     function GetEnumerator: TStepEnum<T>;
  9.     property Current: T read I;
  10.     function By(N: T): TStepEnum<T>;
  11.   end;
  12.  
  13. function TStepEnum<T>.MoveNext: Boolean;
  14. begin
  15.   I := I + Step;
  16.   if Step > 0
  17.     then Result := I <= Stop
  18.     else Result := I >= Stop
  19. end;
  20.  
  21. function TStepEnum<T>.GetEnumerator: TStepEnum<T>;
  22. begin
  23.   Result := Self;
  24. end;
  25.  
  26. function TStepEnum<T>.By(N: T): TStepEnum<T>;
  27. begin
  28.   Step := N;
  29.   I := I - Step;
  30.   Result := Self;
  31. end;
  32.  
  33. function ForStep<T>(AFrom, ATo: T): TStepEnum<T>;
  34. begin
  35.   Result.Stop := ATo;
  36.   Result.Step := ATo;
  37.   Result.I := AFrom;
  38. end;
  39.  
  40. function DoLoop(Start, Stop: Integer; Step: Integer = 1): TStepEnum<Integer>;
  41. begin
  42.   Result := ForStep<Integer>(Start, Stop).By(Step);
  43. end;
  44.  
  45. var
  46.   i: Integer;
  47.   d: Double;
  48. begin
  49.   for i in DoLoop(0, 100, 5) do
  50.     WriteLn(i);
  51.   for i in ForStep<Integer>(0, 100).By(5) do
  52.     WriteLn(i:6);
  53.   for d in ForStep<Double>(0.00, 100.00).By(5.00) do
  54.     WriteLn(d:12:2);
  55. end.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Aruna

  • Hero Member
  • *****
  • Posts: 799
Re: FFS: step
« Reply #2 on: August 04, 2025, 04:30:17 pm »

for i := 0 to 100 step 5 do


PLEASE!!!!

Having to work around the lack of a 'step' in for loops is inelegant, inefficient and prone to error.
Attached zip has a fully working demo which you can easily convert to a reusable function. When first run you will see the first screenshot with a default step value of 5. Second screenshot shows counting up to 100 with the default step size of 5. Third screenshot shows counting down with a step size of 20. This may not be teh best way to do this but this gets the job done  8-)

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #3 on: August 04, 2025, 06:03:54 pm »
You could use enumerator:
  for d in ForStep<Double>(0.00, 100.00).By(5.00) do
    WriteLn(d:12:2);
end.

<snipped a lot .... like A LOT!>

*ROFLMAO*

Only that?

*Gasping for air ....*
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

Fred vS

  • Hero Member
  • *****
  • Posts: 3919
    • StrumPract is the musicians best friend
Re: FFS: step
« Reply #4 on: August 04, 2025, 06:05:31 pm »
Code: Pascal  [Select][+][-]
  1. i := 0;
  2. step := 5;
  3. maxi := 100;
  4.  
  5. while i  <= maxi do
  6.   begin
  7.     writeln(i);
  8.     i := inc(i,step);
  9.   end;
« Last Edit: August 04, 2025, 06:17:50 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: FFS: step
« Reply #5 on: August 04, 2025, 06:43:07 pm »
You could use enumerator:
  for d in ForStep<Double>(0.00, 100.00).By(5.00) do
    WriteLn(d:12:2);
end.

<snipped a lot .... like A LOT!>

*ROFLMAO*

Only that?

*Gasping for air ....*
Only that. It's a generic, more safe than a while-do construct and you should be able to figure out how to shorten it. But you're aiming towards language change, so its a no-go.
And don't be hastily arrogant, please.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

BeniBela

  • Hero Member
  • *****
  • Posts: 959
    • homepage
Re: FFS: step
« Reply #6 on: August 04, 2025, 06:53:24 pm »
But the while loop is three to four times faster than the enumerator

especially loops should be as fast as possible

Ten_Mile_Hike

  • Full Member
  • ***
  • Posts: 140
Re: FFS: step
« Reply #7 on: August 04, 2025, 06:56:44 pm »
Code: Pascal  [Select][+][-]
  1. For x:= 1 to 100 do if x mod 3 =0 then writeln(x);
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #8 on: August 04, 2025, 08:30:53 pm »
You could use enumerator:
  for d in ForStep<Double>(0.00, 100.00).By(5.00) do
    WriteLn(d:12:2);
end.

<snipped a lot .... like A LOT!>

*ROFLMAO*

Only that?

*Gasping for air ....*
Only that. It's a generic, more safe than a while-do construct and you should be able to figure out how to shorten it. But you're aiming towards language change, so its a no-go.
And don't be hastily arrogant, please.

Fortran- check (yes, might be later Fortran's than what Gramps used).
BASIC- check
Modula-2- check (Wirth recognized his screwup) [Oberon too if one wants to step that far ...]
C- check
Python- check
Rust- check

It's a very minor change and it is backwards compatible.

Considering all the other Pascal language basic changes in the last 40 years, this is really not asking much.

Arrogant?  Not at all.
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: FFS: step
« Reply #9 on: August 05, 2025, 10:29:36 am »
But the while loop is three to four times faster than the enumerator
Sure it is.
Personally, I find while-do to be the most suitable cycle for such cases with a step other than 1 or a variable one.
But it is also true that I often forgot the increase statement in the end.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Thaddy

  • Hero Member
  • *****
  • Posts: 19158
  • Glad to be alive.
Re: FFS: step
« Reply #10 on: August 05, 2025, 04:50:10 pm »
My 80's code still works, but do not use. It still works though and is Delphi compatible.
Code: Pascal  [Select][+][-]
  1. program stephack;
  2. { my hack from the TP era still works }
  3. var
  4.   i:integer;
  5. begin
  6.   for i := 0 to 100 do
  7.   begin
  8.     writeln(i);
  9.     inc(PInteger(@i)^,4);
  10.     // newer delphi's need this here:   if i >=100 then break;
  11.   end;
  12. end.
 
A way more advanced one looks like this:
Code: Pascal  [Select][+][-]
  1. {$if fpc_fullversion < 30301}{$error needs 3.3.1 or higher}{$ifend}
  2. // adapted from an example I found somewhere.
  3. {$modeswitch anonymousfunctions}
  4. type
  5.   TFunc<T> = reference to function:T;
  6.  
  7. // captures the variable
  8. function MakeCounter(Start, Increment: Integer): TFunc<Integer>;
  9. begin
  10.   Result := function: Integer
  11.             begin
  12.               Result := Start;
  13.               Inc(Start, Increment);
  14.             end;
  15. end;
  16.  
  17. procedure WriteList(const Source: TFunc<Integer>; Count: Integer);
  18. begin
  19.   while Count > 1 do
  20.   begin
  21.     Write(Source():4);
  22.     Dec(Count);
  23.   end;
  24.   Writeln(Source():4);
  25. end;
  26.  
  27. var
  28.   evenNumbers: TFunc<Integer>;
  29.   decades: TFunc<Integer>;
  30. begin
  31.   evenNumbers := MakeCounter(0, 2);
  32.   decades := MakeCounter(0, 10);
  33.   WriteList(evenNumbers, 10);
  34.   WriteList(decades, 10);
  35.   readln;
  36. end.
« Last Edit: August 05, 2025, 05:29:38 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #11 on: August 06, 2025, 04:54:51 pm »
Code: Pascal  [Select][+][-]
  1. For x:= 1 to 100 do if x mod 3 =0 then writeln(x);

Wasted loops and two added operations (mod and test for 0).

for ... Step for increment of 1 or increment of (eg 3) is exactly the same at the machine level.

Each example below a constant is changed from a 1 to a 3:

ARM:
Code: Pascal  [Select][+][-]
  1. # [158] for i := 0 to NTIDS-1 do
  2.         movz    w19,#65535
  3.         .align 2
  4. Lj40:
  5.         add     w0,w19,#1     //  <-- chg the #1 to #3 for step of 3
  6.         uxth    w0,w0
  7.         mov     w19,w0
  8.  

x86_64:
Code: Pascal  [Select][+][-]
  1. # [158] for i := 0 to NTIDS-1 do
  2.         movw    $65535,%bx
  3.         .align 3
  4. Lj42:
  5.         addw    $1,%bx   // <-- as above for the $1
  6.  
« Last Edit: August 06, 2025, 08:17:10 pm by AlanTheBeast »
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #12 on: August 06, 2025, 04:56:28 pm »
Code: Pascal  [Select][+][-]
  1. i := 0;
  2. step := 5;
  3. maxi := 100;
  4.  
  5. while i  <= maxi do
  6.   begin
  7.     writeln(i);
  8.     i := inc(i,step);
  9.   end;

Another example of elegantless code where the simple self explaining 'step' does wonders in various languages.
It is also more efficient (see my other post this am with examples in assembler generated by fpc for ARM and x86)
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #13 on: August 06, 2025, 05:02:26 pm »
But it is also true that I often forgot the increase statement in the end.

This is practically my default, esp when { p := p^.next } but also in while or repeat loops.

Validates another example where the "contract*" should be set up in the loop statement (for n = 0 to 100 step 5 do {};)

*Design by contract.
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: FFS: step
« Reply #14 on: August 06, 2025, 11:54:15 pm »
But the while loop is three to four times faster than the enumerator

See the assembler examples above.  Adding "step" to the statement makes zero change to the compiled code.

Not sure why you believe a while loop would be faster.
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

 

TinyPortal © 2005-2018