Wednesday 22 June 2022

A SET up

- or how the for-in statement changed  recently.


Before Delphi 10.4, the statement:

for integer in [] do 

would operate on a set, but since then it now operates on an array. Which then also means a bit of different behaviour.

I had missed this change completely, and only recently gotten aware of it since we had a build issue - mixing source from different IDE versions. (BTW: Do not do that).

Since it previously worked on a set - the "list" when traversed would be an ordered list of values with an ordinal value no bigger than 255, and no more than 256 elements, that is now changed. I will list a few examples - illustrating the pre-10.4 behaviour compared to 10.4 and later.

Duplicates and ordering


var
  i: integer;
begin
  for i in [42, 10, 42, 3, 42, 7] do
    WriteLn(i.ToString);
end.

returns:

10.4+: 42, 10, 42, 3, 42, 7
pre10.4: 3,7,10,42

Range


var
  i: integer;
begin
  for i in [42, 365, MaxInt] do
    WriteLn(i.ToString);
end.

10.4+: 42, 365, MaxInt
pre10.4: Does not compile - In 10.3 you get an E1012 Constant expression violates subrange bounds (earlier you might also get an E2024)

To solve that you could replace it with something like:

uses
  System.Types,
  System.SysUtils;

var
  i: integer;
begin
  for i in TIntegerDynArray.Create(42, 365, MaxInt) do
    WriteLn(i.ToString);
end.

I do think the change is a step up, and does syntax-wise work more like one would expect, so a change for the greater good - but do be aware of the change of behaviour. Another benefit of a newer version is the usage of inline variable declaration and type inference, like in this case:

for var i in [42, 10, 42, 3, 42, 7] do
    WriteLn(i.ToString);

/Enjoy