Tuesday, November 20, 2018

For..to..step in Delphi!

Today I was porting some legacy code and noticed a weird warning:

image

Weird warning, I thought. Obviously the loop variable can be passed as a var parameter as the code compiles. Why a warning and not an error, then?

Stefan later reminded me that warnings are quite extensively covered in the documentation. Indeed, the docs for W1015 clearly state:

This is a warning because the procedure which receives the control variable is able to modify it, thereby changing the semantics of the FOR-loop which issued the call.

Ah! So they actually want to say “… FOR-Loop variable ‘i’ should not be …

Furthermore, this brings several interesting possibilities to the table. For example, we can finally write for..to..step loops in Delphi!

program ForInStep;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

procedure Step(var loop: integer; step: integer);
begin
  loop := loop + step - 1;
end;

var
  i: integer;

begin
  for i := 1 to 10 do begin
    Writeln(i);
    Step(i, 2);
  end;
  Readln;
end.

Indeed, this works!

image

Danger, Will Robinson!

To be clear, I do not recommend writing such code. If you get warning W1015, you should rewrite the code. Such code is hard to maintain and will eventually cause you big problems.

I certainly did fix the original code although the method that was called from the for loop did not modify its var parameter. (It was declared var and not const because the method was written before const parameters were introduced to Delphi. Oh, the joys of legacy code!)

1 comment:

  1. Just a hobbiest here, but for over a decade now Ive done the following:
    //You can use integer type just as easily

    procedure Stepper(Lo,Hi,Step:Double);
    begin
    repeat
    Form1.memo1.Lines.Add(floattostr(Lo));
    Lo:=Lo+Step;
    until Lo>Hi;
    end;

    procedure TForm1.Button1Click(Sender:TObject);
    begin
    Stepper(3.03, 28.127, 3.009);
    end;

    ReplyDelete