Why is the assignment in the for...in loop disallowed by the compiler?
procedure TForm1.Button1Click(Sender: TObject);
Var
ars : Array [0..10] of Integer;
s : Integer;
ct : Integer;
begin
ct := 0;
for s in ars do
Begin
s := ct; // Does not compile!
Inc(ct);
End;
End;
This is not supported, just as even simple loop iterator variables cannot be modified in a "normal" for loop. Even if this were supported in a for-in, it would not make much sense in this case.
Integers are value types, so in each iteration of the loop all that would be achieved is that s would be initialised to a value from an element the array and then s overwritten by Ct.
But the array contents would not be modified and the net effect of the code would be "no change".
To get what you expect from a for-in you would have to be able to iterate using a suitable reference type (in this case a PInteger - pointer to integer) yielding references to the array elements, rather than copies of the values of those elements. A new value for each element could then be assigned using the dereferenced pointer:
var
ars : array [0..10] of Integer;
s : PInteger;
ct : Integer;
begin
ct := 0;
for s in ars do // << this WON'T yield pointers to the array elements ..
begin
s^ := Ct; // .. but if it did you could then write this
Inc(ct);
end;
end;
But don't get excited - this won't work either, it merely demonstrates the nature of the problem stemming from the difference in a reference vs a value.
I know nothing about Delphi specifically. However, most languages don't allow you to assign to the iteration variable in a foreach
. Why do you want to do this?
just use a while loop instead.
procedure TForm1.Button1Click(Sender: TObject);
Var
ars : Array [0..10] of Integer;
i : Integer;
ct : Integer;
begin
ct := 0;
i := 0;
while i < Length(ars) do
Begin
ars[i] := Ct; //Does Compile!
Inc(ct);
inc(i);
End;
End;
To understand this better, I would say, "understand s as being controlled by the for s in .... construct", that is to say, while s is in control of the for loop, a well written compiler for almost any language will block you from doing this. Any compiler that is not well enough written to block this, should be backed up by a compiler warning, or a lint-tool that indicates you are doing something that is at best, terribly bad style, and at worst, perhaps will lead to some "undefined" behavior that would be hard to predict. What happens if you set s to a value that is higher than the Length(ars)? Should the loop abort, or should it continue?
The variable S is just a copy of the value in the array, so changing it would have no meaning. The construct
for s in ars do
is basically equivalent to
for i := low(ars) to high(ars) do
s := ars[i]
so there's no point assigning to S. Do the loop this way
procedure TForm1.Button1Click(Sender: TObject);
Var
ars : Array [0..10] of Integer;
i : Integer;
ct : Integer;
begin
ct := 0;
for i := low(ars) to high(ars) do
Begin
ars[i] := ct;
Inc(ct);
End;
End;