POV-Ray

The Persistence of Vision Raytracer (POV-Ray).

This is the legacy Bug Tracking System for the POV-Ray project. Bugs listed here are being migrated to our github issue tracker. Please refer to that for new reports or updates to existing ones on this system.

Attached to Project: POV-Ray
Opened by Juha Nieminen - 2010-03-22
Last edited by Christoph Lipka - 2010-06-19

FS#84 - A for-loop construct

Many people clearly miss a simple for-loop construct in povray. It is indeed true that probably at least 99% of #while loops out there have the form of a simple for-loop. It’s much rarer to have to use more exotic forms of looping supported by the #while mechanism. Thus it would make sense if a #for construct would be added which would make writing such loops much easier and convenient.

The only remaining question would be the syntax.

IMO the for-loop construct should implicitly declare a local variable of a specified name, automatically increment it during the loop, and then undefine it after the loop ends. It could perhaps be something along the lines of:

#for(<identifier name>, <initial value>, <final value> [, <step>])
  <loop body>
#end

Example:

#for(Counter, 1, 10) // 'Counter' gets values 1, 2, 3, ..., 10
  #debug concat(str(Counter, 0, 0), "\n")
#end
#for(Counter, 1, 10, 3) // 'Counter' gets values 1, 4, 7, 10
  #debug concat(str(Counter, 0, 0), "\n")
#end

I think this syntax ought to be relatively easy to implement (compared to more “traditional” syntaxes, such as something like “for Counter = 1 to 10” or the C syntax, which would be a lot more complicated).

Of course this raises a couple of questions:

1) What happens if ‘Counter’ was already declared as an identifier? One of three possibilities comes to mind:

  • The ‘Counter’ in the for-loop replaces the previous identifier, as a regular #local command would.
  • The ‘Counter’ in the for-loop hides the identifier for the duration of the loop, and unhides it afterwards.
  • A syntax error is given (ie. the identifier name must be unused).

2) Should the user be able to modify the counter variable from inside the body of the loop? Something like this comes to mind as viable:

// Prints the values 1, 2, 3, 9 and 10
#for(Counter, 1, 10)
  #debug concat(str(Counter, 0, 0), "\n")
  #if(Counter = 3) #local Counter = 8; #end
#end

Alternatively the counter variable could be read-only.

Additionally, it could be nice if #break could be used to immediately jump out of the current loop (either #while or #for).

Closed by  Christoph Lipka
Saturday, 19 June 2010, 00:59 GMT
Reason for closing:  Implemented
Additional comments about closing:  

No beta tester feedback for way over a month now; I consider that good news.

Admin
Christoph Lipka commented on Monday, 22 March 2010, 21:09 GMT

I fully second this feature request.

As for the details, for simplicity as well as consistency with current practice I'd advocate a #for loop to be fully equivalent to a corresponding #while loop, i.e. that the following have exactly the same effects and side-effects inside and after the loop:

#for(A,B,C,D)
  //...
#end
#if(D=0) #error "Loop step value must be non-zero!\n" #end
#local A = B;
#while((D>0)?(A<=C):(A>=C))
  //...
  #local A = A + D;
#end
Juha Nieminen commented on Friday, 26 March 2010, 15:00 GMT

One more thing: If the final value is smaller than the initial value, the counter could go backwards automatically. The sign of the optional step value could be ignored (in other words, a step value of 3 and a step value of -3 would be completely identical, as the sign is ignored). This way you could write:

// Prints the values 5, 4, 3, 2, 1:
#for(Counter, 5, 1)
  #debug concat(str(Counter, 0, 0), "\n")
#end

// Prints the values 10, 8, 6, 4, 2, 0:
#for(Counter, 10, 0, 2)
  #debug concat(str(Counter, 0, 0), "\n")
#end
Admin
Christoph Lipka commented on Friday, 26 March 2010, 16:25 GMT

Making the loop "direction" depend on the bounds is a bad idea, as it is frequently desired that the loop not be executed if end < start, as demonstrated by the following typical use pattern:

#declare MyArrayMaxCapacity  = 1024;
#declare MyArrayUsedCapacity = 0;
//...
#for (ArrayIndex, 0, MyArrayUsedCapacity-1)
  //...
#end

To my knowledge, virtually all programming languages do not auto-adjust the loop direction.

Admin
Christoph Lipka commented on Friday, 16 April 2010, 15:32 GMT

Implemented with change #4941.

Admin
Christoph Lipka commented on Sunday, 18 April 2010, 15:15 GMT

Implemented #break statement with change #4942.

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing