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.

Tasklist

FS#84 - A for-loop construct

Attached to Project: POV-Ray
Opened by Juha Nieminen (Warp) - Monday, 22 March 2010, 16:00 GMT
Last edited by Christoph Lipka (clipka) - Saturday, 19 June 2010, 00:59 GMT
Task Type Feature Request
Category Backend → Parser/SDL
Status Closed
Assigned To No-one
Operating System All
Severity Very Low
Priority Low
Reported Version Not applicable
Due in Version 3.70 beta 37
Due Date Undecided
Percent Complete 100%
Votes 1
Private No

Details

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).

This task depends upon

Closed by  Christoph Lipka (clipka)
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.
Comment by Christoph Lipka (clipka) - 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
Comment by Juha Nieminen (Warp) - 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
Comment by Christoph Lipka (clipka) - 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.

Comment by Christoph Lipka (clipka) - Friday, 16 April 2010, 15:32 GMT
  • Field changed: Status (New → Requires testing)
  • Field changed: Due in Version (Undecided → 3.70 beta 37)
  • Field changed: Percent Complete (0% → 100%)

Implemented with change #4941.

Comment by Christoph Lipka (clipka) - Sunday, 18 April 2010, 15:15 GMT

Implemented #break statement with change #4942.

Loading...