POV-Ray : Newsgroups : povray.pov4.discussion.general : I want to be rid of my stupid mistakes Server Time
29 Jun 2024 01:20:41 EDT (-0400)
  I want to be rid of my stupid mistakes (Message 41 to 50 of 53)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 3 Messages >>>
From: clipka
Subject: Re: I want to be rid of my stupid mistakes
Date: 22 Jul 2009 15:05:01
Message: <web.4a67621297aca27169042aac0@news.povray.org>
"Trevor G Quayle" <Tin### [at] hotmailcom> wrote:
> I do agree that a for loop would be more concise and I'm not trying to hinder
> you from getting it.  It was more a matter of showing that adding a #for
> wouldn't add functionality that the current #while loop can't already do, it
> just makes things more concise and recognizable, and perhaps easier to use (in
> my earlier days I often wished I did have a for loop, however now, I just got
> used to using the while loop).  If whatever programming overhead involved in
> adding #for loop functionality is worth the value of having it, then, by all
> means, it could/should be added.  The value being in simpler coding rather than
> added functionality.

Ah, so then it seems we're actually of the same opinion.

The fact that from a functionality point of view, a #while() loop is perfectly
fit to be used instead of a #for loop (or any other possible loop for that
matter) is not much news to me though - and given how it's introduced in the
POV-Ray manual I'd be surprised if it was news to any significant number of
people, so I naturally assumed you were doubting its added value.


> An example is placing non-intersecting spheres in a box.  If the maximum count
> is greater than what can actually fit in the volume (i.e., the loop reaches a
> point where it can no longer find a big enough space to place a new sphere, but
> keeps trying because the max number of objects hasn't been reached), an inifnite
> loop will be encountered.  This only a simple demonstration as, in reality, it
> should be obvious what is causing the inifinite loop once it is located,
> however, the presence of the inifinite loop would not (likely) be obvious by
> simple examination of the written code (i.e. it is not a coding error).

Okay, that's a different point though. Note however that this is a perfect
example for where code analysis would come to its limits identifying the
endless loop; after all, it's not an issue of code structure but a geometrical
one, and you cannot come up with an algorithm to solve every possible such
decision. Even worse, what if there would theoretically be just enough space
for another such a sphere, but the random number generator happens to never
ever produce the respective position with the given seed?

So in this case it's up to the developer to think of a suitable upper bound when
to terminate the loop, and design it right into it:

  #declare SpheresPlaced = 0;
  #declare i = 0; #while ((Spheres < MaxSpheres) & (i < MaxLoops))
    ...
    #if (Whatever)
      ...
      #declare Spheres = Spheres + 1;
      // maybe also #declare i = 0;
    #end
    ...
  #declare i = i + 1; #end

Something like this. I don't think there's much that will save you from putting
this kind of thought into a non-straightforward counting loop.


I guess an interesting syntax for such constructs would be something like this:

  #for Spheres = 1 to 10000
    ...
    #if (Whatever)
      ...
    #else
      #retry 10 // new keyword, in addition to the #for keyword
    #end
  #end

which would be to say, if the condition does not hold true, abort the current
iteration and re-iterate without incrementing the counter - unless you tried 10
times in a row without success already, in which case abort the loop.


Post a reply to this message

From: clipka
Subject: Re: I want to be rid of my stupid mistakes
Date: 22 Jul 2009 15:20:00
Message: <web.4a6765b197aca27169042aac0@news.povray.org>
"Trevor G Quayle" <Tin### [at] hotmailcom> wrote:
> Adding the #for loop only solves the problem with a misplaced or missing
> increment statement, which is purely a programmer's error that can be largely
> avoided with a little diligence by the programmer.  Of course this is the type
> of infinite loop scenerio that the OP is referring to.
>
> This will not solve other infinite loop problems that are not related to
> programmer error such as conditional statements that are never satisfied due to
> some issue that is not superficially apparent.

Those, to, by definition are programmer errors, BTW.


> The #for loop would add some ease and conciseness to the coding end and help
> users avoid this programming error, but it would not add any functionality
> overall that isn't already achievable through a properly constructed #while
> loop.

*No* loop does. #while() is perfectly able to save it all, when properly
combined with #if() constructs.

Like with #for loops, the corresponding #while replacement may become
cumbersome, but it's perfectly possible.


> One further item on the potential creation of #for loops:  Would they be best
> end-bracketted with the general #end statement (as #while, #if, #switch and
> #macro all use)? Or would it be more appropriate to add a "#next" statement or
> even "#next n" statement instead?  #end would make it more consistent with
> current programming practice, but #next would make the #for loop construct more
> visible and identifiable.

Whith all other statements bracketed with #end, for consistency's sake there's
virtually no other way as to close them with #end, too. And why not?

Sure, a "#next i" statement helps identify the "#for" statement it belongs to,
but then again you can achieve the same through good indentation, or using
"#end // i".


> Along this line of thinking, perhaps more specific
> #end statements would also be more appropriate for the other situations as
> well: #while/#wend, #if/#endif, #switch/(#send?), #macro/(#mend?).  Of course
> you would likely keep the #end functionality for backwards compatibility.

I'd personally favor completely different bracketing rules anyways, using {}
instead (to use the same bracketing rules as for object statements, and
functions for that matter). Though I know various people (I don't dare make any
estimate here) would disagree.

I don't think a #wend, #send, #mend etc. is really necessary, and #endif would
make this inconsistent anyway.

If at all (there is a bit of a point here to identify the type of statement that
you expect to be ending, so as to enable the parser to better pin down where you
goofed the #end matching), I'd rather go for "#end if", "#end macro" etc.


Post a reply to this message

From: scott
Subject: Re: I want to be rid of my stupid mistakes
Date: 23 Jul 2009 04:07:24
Message: <4a681a3c@news.povray.org>
>  How can the checker know that the result is different each time the macro
> is called?

It doesn't, it just assumes it is to avoid a false positive situation.


Post a reply to this message

From: Trevor G Quayle
Subject: Re: I want to be rid of my stupid mistakes
Date: 23 Jul 2009 09:35:00
Message: <web.4a6865f997aca27181c811d20@news.povray.org>
A further thought I had this morning rather than adding an *infinite* loop
checker or loop_limit variable.
Typically if a render is parsing too long and a user gets suspicious, the user
will terminate the program.  Currently this simply posts the message "Render
cancelled by user." plus stats.  It would maybe be of debuggin assistance to
also report the line number where parsing was at the time of interruption
(similar to how an error does) and also (if it may be possible) the current
number of iterations the current loop(s) have been through.  You would likely
want it to report the number of iterations for any currently active loop (in
the case of nested loops) as it could be any of them that are the issue, not
just the most recent (any closed or inactive loops can be ignored).

EG:

01 #declare i=0;
02 #while (i<10)
03  #declare i=i+1;
04 #end
05 #declare i=0;
06 #while (i<100)
07   #declare j=0;
08   #while (j<100)
09     #declare j=j+1;
10   #end
11 #end

The user breaks the program while it is at line 09.
The first loop is inactive [line 2: #while (i<10)] as it reached its #end
statement, but the next two loops [line 6: #while (i<100), line 8: #while
(j<100)] are currently active, however POV doesn't know which is the problem
(the user should be able to tell that the j loop is fine as it has its counter,
but the i loop is infinite as the counter was forgotten.

In this case, POV could report (similar to error reporting) something along the
lines of:

Render cancelled by user.
Break point:
File: C:\POVDIR\POVFILE.pov  Line: 9
     #declare j=j+1;
Active loop:
File: C:\POVDIR\POVFILE.pov  Line: 6
#while (i<100)
Iteration count: 12345
Active loop:
File: C:\POVDIR\POVFILE.pov  Line: 8
  #while (j<100)
Iteration count: 67


The user can reference this to see where the file was terminated (line 9) and
the iteration count of the current active loops (line 6: 12345, line 9: 67) and
pinpoint the problem.  From this the user can infer that it may be the line 6
loop that is the problem as it has gone through a larger number of iterations
(perhaps larger than should be expected), whereas the line 8 loop is within the
expected loop count still.  Further investigation would reveal the omitted i
increment statement causing the infinite loop.

All this would be done with breaking the current implementation of the SDL.  It
would simply require reporting of the current line (which should be easy as it
is already done for errors) plus the addition of loop counters.  I'm not
familiar with the code, but I should think it wouldn't be an overly difficult
task to add this as POV would already need to keep track of open loops within
it's code parsing.

Any thoughts?

-tgq

-tgq


Post a reply to this message

From: clipka
Subject: Re: I want to be rid of my stupid mistakes
Date: 23 Jul 2009 14:05:00
Message: <web.4a68a63f97aca271aca5323b0@news.povray.org>
"Trevor G Quayle" <Tin### [at] hotmailcom> wrote:
> Render cancelled by user.
> Break point:
> File: C:\POVDIR\POVFILE.pov  Line: 9
>      #declare j=j+1;
> Active loop:
> File: C:\POVDIR\POVFILE.pov  Line: 6
> #while (i<100)
> Iteration count: 12345
> Active loop:
> File: C:\POVDIR\POVFILE.pov  Line: 8
>   #while (j<100)
> Iteration count: 67

Nice one. That would indeed be handy.

> I'm not
> familiar with the code, but I should think it wouldn't be an overly difficult
> task to add this as POV would already need to keep track of open loops within
> it's code parsing.

I haven't paid much attention to loop handling yet, but nested loops are handled
by recursive calls, and I guess aborting parsing is done by throwing an
exception; so it would mean adding...

- a local variable to count loop iterations while in a loop
- code to catch the exception while in a loop, and throw it onward with added
information about the current loop
- code to pass the detailed information to the front-end
- code in the front-end to output the information

Nothing that sounds dramatically complicated.

Being on it, it would be nice to have the same mechanism kick in if parsing is
aborted for any other reason.

Another thing that would greatly faciliate debugging would be a simpler syntax
to output a single variable, so that for instance

  #declare Foo = 47.11000;
  #local Bar = sphere { <0,0,0>, 1 }

  #debug_var Foo, Bar
  #debug_var Foobar

might print:

  Foo (global): 47.11
  Bar (local): object
  Foobar: undefined


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: I want to be rid of my stupid mistakes
Date: 20 Aug 2009 02:52:47
Message: <4a8cf2bf@news.povray.org>
clipka wrote:

> "scott" <sco### [at] scottcom> wrote:
>> I'm not saying it's possible to detect whether any program will stop or
>> not. I'm saying that in *some* cases you can relatively easily detect
>> that it won't stop without changing the functionality.
> 
> I'm definitely repeating myself here: Those easy cases would come packaged
> with too many not-so-easy special cases.
> 
> Sure you can detect a simple
> 
>   #while (i < N)
>     //#declare i=...
>   #end
> 
> as being an infinite loop, but that's an absolutely trivial case; as soon
> as you go from there to
> 
>   #while (i < N)
>     ...
>     //#declare i=...
>     ...
>   #end
> 
> then if you don't find a "#declare i=...", you *must* examine the "..."
> thoroughly before you can conclude that the user really forgot it.
> 
> Of course, if you *do* find a "#declare i=..." in there, you can tell for
> sure the user did *not* forget it; but that doesn't get us any further.
> 
> The bottom line is that a potentially-infite-loop detector would be a
> quite complex piece of code, even if it were just to catch some standard
> cases. There would be much easier and more useful remedies for the
> forgotten-increment ailment.

I think most of the cases previously posted here are actually solvable. That
is, you can avoid thinking it's infinite when it's not (you can't avoid the
opposite, but it's OK, we don't have to detect all cases, and it's
impossible anyway). I have yet to see someone post a convincing code
snippet that would give a false positive.

#declare I=0;
#while (I < Limit)
   //...
#end

If neither 'I' nor 'Limit' are ever mentioned inside the loop, it's
infinite. Otherwise, it may be infinite, but assume it's not and let it
run.

#declare I=0;
#while (I < Limit)
    //...
    #include "file.inc"
#end

Just assume it's not infinite if there is an include, since it's prone to
way too many variables. For example, the user could edit file.inc in the
middle of the parsing to have #declare I=Limit;


Post a reply to this message

From: clipka
Subject: Re: I want to be rid of my stupid mistakes
Date: 20 Aug 2009 05:39:48
Message: <4a8d19e4$1@news.povray.org>
Nicolas Alvarez schrieb:
> #declare I=0;
> #while (I < Limit)
>    //...
> #end
> 
> If neither 'I' nor 'Limit' are ever mentioned inside the loop, it's
> infinite.

Not necessarily:

#macro Next()
   #declare I=I+1;
#end

#declare I=0;
#while (I < Limit)
   Next()
#end

No mention of I anywhere in the loop, yet perfectly finite.

You *must* dig into *every* macro to catch this.


Post a reply to this message

From: scott
Subject: Re: I want to be rid of my stupid mistakes
Date: 20 Aug 2009 09:48:28
Message: <4a8d542c@news.povray.org>
> #macro Next()
>   #declare I=I+1;
> #end
>
> #declare I=0;
> #while (I < Limit)
>   Next()
> #end
>
> No mention of I anywhere in the loop, yet perfectly finite.
>
> You *must* dig into *every* macro to catch this.

The parser re-parses the macro every time it is called though, doesn't it? 
So the parser simply needs to look out for any "#declare I" any time it is 
parsing commands within the loop, no matter if it is in a macro or not.


Post a reply to this message

From: Warp
Subject: Re: I want to be rid of my stupid mistakes
Date: 20 Aug 2009 10:45:36
Message: <4a8d618f@news.povray.org>
scott <sco### [at] scottcom> wrote:
> > #macro Next()
> >   #declare I=I+1;
> > #end
> >
> > #declare I=0;
> > #while (I < Limit)
> >   Next()
> > #end
> >
> > No mention of I anywhere in the loop, yet perfectly finite.
> >
> > You *must* dig into *every* macro to catch this.

> The parser re-parses the macro every time it is called though, doesn't it? 
> So the parser simply needs to look out for any "#declare I" any time it is 
> parsing commands within the loop, no matter if it is in a macro or not.

  It doesn't necessarily parse it every time. You could have something like:

#declare I=0;
#while (I < Limit)
    #if(rand(someSeed) < 0.5)
        Next()
    #end
#end

-- 
                                                          - Warp


Post a reply to this message

From: scott
Subject: Re: I want to be rid of my stupid mistakes
Date: 20 Aug 2009 10:53:35
Message: <4a8d636f$1@news.povray.org>
>  It doesn't necessarily parse it every time. You could have something 
> like:
>
> #declare I=0;
> #while (I < Limit)
>    #if(rand(someSeed) < 0.5)
>        Next()
>    #end
> #end

Ah yes, I think the conclusion we came to before is that anything that 
involves macro calls has to be assumed finite, because as clipka said you 
would need to search all macros to see if 'I' was redefinied anywhere, and 
that seems a bit wasteful.


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 3 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.