Search code examples
delphifor-loopdelphi-xe7

Convert For loop to not use variables


I use Virtual Treeview a lot in my app. And to build nodes, I use this procedure, when I know nodes will have children nodes:

 VTV.BeginUpdate;
  VTV.Clear;
  for i := 0 to Length(vArray) - 1 do
  begin
    // Add a node to the root of the Tree
    if i = 0 then
    begin
      Node := VTV.AddChild(nil);
      Data := VTV.GetNodeData(Node);
    end
    else
    begin
      if vArray[i].Level = 0 then Node := VTV.AddChild(nil)
      else if vArray[i].Level > vArray[i - 1].Level then Node := VTV.AddChild(Node)
      else if vArray[i].Level < vArray[i - 1].Level then
      begin
        Node := Node.Parent;
        for j := 1 to (vArray[i - 1].Level - vArray[i].Level) do // line#: 428 warning: j not used!
          Node := Node.Parent;
        Node := VTV.AddChild(Node);
      end
      else
      begin
        Node := Node.Parent;
        Node := VTV.AddChild(Node);
      end;
      Data := VTV.GetNodeData(Node);
    end;
    // Create link to your data record into node
    Data.IndexInMyData := i;
    vArray[Data.IndexInMyData].NodePointer := Node;
  end;
  VTV.EndUpdate;

When I run Peganza's Pascal Expert (Pascal Analyzer integrated into IDE) it gives me message that 'j' variable is not used in For-loop:

[Pascal Expert] WARN42: Standards.pas(428): j For-loop variables not used in loop

I understand the message and it proved to be useful in other cases where I used 'i' instead of 'j' and such (from copy-pasted code), but not in this case. Since I use the same code in many many Virtual Treeviews, I have a lot of occurrences of this warning.

Any suggestion how I can change this For-loop so I don't get this message anymore?

for j := 1 to (vArray[i - 1].Level - vArray[i].Level) do
          Node := Node.Parent;

Preferrably I would like same length or shorter than currently, I don't want to have something like this - this is too much code:

j:=1;
while j <= (vArray[i - 1].Level - vArray[i].Level) do
begin
  Node := Node.Parent;
  Inc(j);
end;

Solution

  • I don't think that there's any way to write that code in a cleaner way. Stepping back, there are variety of uses of for loops, but perhaps the two main ones are as follows:

    • Perform an action on each member of a collection.
    • Perform an action N times.

    This is obviously a simplification but if you look at the for loops in your code base you'll see that they invariably fall into one category or the other.

    Now, the code under consideration falls in to the second category. It is of this form:

    for I := 1 to N do
      Foo();
    

    How else could you write this? You could use another form of loop, of which there is while and repeat. As you have observed in the case of while, neither results in cleaner code. The other option would be to use a recursive implementation to bring about the iteration. That will not be simpler.

    The conclusion to this is that your static analysis tool is rejecting a common and valid form of iteration. The problem is not that your code is weak, but that the static analysis is mis-diagnosing a problem that does not exist.

    Solution: suppress or ignore these specific static analysis warnings.