discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Something annoying about "C-like for"

A
adrianv
Sun, Feb 2, 2020 3:22 AM

Ronaldo wrote

In C you can create "output" any time you want.  You can do the same
thing
in openscad using concat, but I assume that would be slow compared to
your
posted approach.  In my posted example I built up the output using
concat.

I don't see how concat may be of any help here. If your code is:

My remark had to do with the ability to map the C code example I wrote that
computes nophead's list of rotations to OpenSCAD.  That example looked
something like

for(i=0, rot[0]=init_value; i<max; rot[i+1] = <something> * rot[i], i++);

In this example, rot is "growing" at each iteration.  To map this code to
OpenSCAD you need a method to grow rot at each iteration.  That method is
concat.

Note that this is really just an aside, and I don't think it's the right way
for nophead to solve his problem.  Also, as you note, it has nothing to do
with the basic problem, which is dealing with the extra evaluation of the
iteration block.

--
Sent from: http://forum.openscad.org/

Ronaldo wrote >> >> In C you can create "output" any time you want. You can do the same >> thing >> in openscad using concat, but I assume that would be slow compared to >> your >> posted approach. In my posted example I built up the output using >> concat. >> > > I don't see how concat may be of any help here. If your code is: My remark had to do with the ability to map the C code example I wrote that computes nophead's list of rotations to OpenSCAD. That example looked something like for(i=0, rot[0]=init_value; i<max; rot[i+1] = &lt;something> * rot[i], i++); In this example, rot is "growing" at each iteration. To map this code to OpenSCAD you need a method to grow rot at each iteration. That method is concat. Note that this is really just an aside, and I don't think it's the right way for nophead to solve his problem. Also, as you note, it has nothing to do with the basic problem, which is dealing with the extra evaluation of the iteration block. -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Sun, Feb 2, 2020 11:44 AM

The general scheme of the "C-like for" in OpenSCAD is:

[ for( initializations; test; computations ) output ]

where the test is done after the initializations and each iterated
computation; the output is implicitly done just *after *the test.

As a proposal for an alternative syntax and semantic, consider:

[ for( initializations; computations; test ) output ]

where the output is implicitly done just after each iterated computation
and *before *the test that follows it.  Note that in this form the
initializations are not special initial computations as happens in the
current form. They produce no output.

To not break current codes, both forms would be accepted, each one with its
own semantics.

With that alternative form, nophead's rotations could be expressed as:

rot0 = init_rot(tangents);
rotations = [rot0, for( i = 0;

                      i = i+1,
                      rot = rft(i)*rot;
                    i < last) rot];

without any extra computations to be filtered but with the special initial
case being dealt out of the "for". Other possibility would be:

rotations = [for( i = 0;

                rot = i==0 ? init_rot(tangents) : rft(i)*rot,

                i = i+1;

              i <= last) rot];

I agree that the current syntax/semantics would be more natural for the
semantics of the alternative form once the output comes syntactically just
after the computations (and that was my first understanding of it). But
there is no way back.

The general scheme of the "C-like for" in OpenSCAD is: [ for( initializations; test; computations ) output ] where the test is done after the initializations and each iterated computation; the output is implicitly done just *after *the test. As a proposal for an alternative syntax and semantic, consider: [ for( initializations; computations; test ) output ] where the output is implicitly done just after each iterated computation and *before *the test that follows it. Note that in this form the initializations are not special initial computations as happens in the current form. They produce no output. To not break current codes, both forms would be accepted, each one with its own semantics. With that alternative form, nophead's rotations could be expressed as: rot0 = init_rot(tangents); rotations = [rot0, for( i = 0; i = i+1, rot = rft(i)*rot; i < last) rot]; without any extra computations to be filtered but with the special initial case being dealt out of the "for". Other possibility would be: rotations = [for( i = 0; rot = i==0 ? init_rot(tangents) : rft(i)*rot, i = i+1; i <= last) rot]; I agree that the current syntax/semantics would be more natural for the semantics of the alternative form once the output comes syntactically just after the computations (and that was my first understanding of it). But there is no way back.
RD
Revar Desmera
Mon, Feb 3, 2020 12:58 AM

I would love comma separated subexpressions in the conditional.  Because otherwise, I end up with things like:

faces = [
for(
first = true,
finishing = false,
finished = false,
plen1 = len(prof1),
plen2 = len(prof2),
i=0, j=0, side=0;

	!finished;

	[INSERT CALCULATIONS HERE]
	face = [p1, p3, p2],
	i = i + (side? 1 : 0),
	j = j + (side? 0 : 1),
	first = false,
	finished = finishing,
	finishing = i>=plen1 && j>=plen2
) if (!first) face

]

  • Revar

On Feb 1, 2020, at 7:07 AM, nop head nop.head@gmail.com wrote:

Perhaps to fix Ronaldo's issue allow comma separated expressions in the test part that only get executed if the test passes, before the output.

On Sat, 1 Feb 2020 at 14:50, adrianv <avm4@cornell.edu mailto:avm4@cornell.edu> wrote:
Well....kind of.  The attraction of this loop structure is that you can
assign and reassign variables in the iteration part.  And while it may look
C-like, OpenSCAD is not C.  In OpenSCAD the loop body isn't "executed" it is
output.  In C you would actually do your computations in the output part at
the end.  But the whole reason to use this structure in OpenSCAD is so you
can reassign variables.  This means the computation all happens in the
iteration block.  Here's a simple example:

// Produces length n vector counting from 0
function example(n) =
[each  // Needed to avoid singleton list output
for(output=[], i=0;
i<=n;
output=concat(output,[i]),  // Here's the computation!
i=i+1,
dummy=echo(i=i,output=output))
if (i==n) output  // Output only in the last iteration
];

Note how I can repeatedly add to the output variable without the need for
recursion?  So there are two potential issues.  One issue is in getting the
answer out.  Here you see I need an "if" to output the answer when the
computation is done with a duplicated test for loop termination, which is
easy to detect since the termination test is very simple in this case.  The
second issue as Rinaldo notes is that the iteration block runs an extra
time---it must run when i=n even though I don't want output for this case.
So this can produce an error, or it can waste time.

So running echo(example(4)) produces:

ECHO: i = 1, output = [0]
ECHO: i = 2, output = [0, 1]
ECHO: i = 3, output = [0, 1, 2]
ECHO: i = 4, output = [0, 1, 2, 3]
ECHO: i = 5, output = [0, 1, 2, 3, 4]
ECHO: [0, 1, 2, 3]

nophead wrote

Isn't it exactly the same as C? The iteration part is done after the loop
body is executed and the test is done before it.

E.g.
initialisation;
while(test) {
....
iteration;
}

So iteration is executed the same number of times as the body and the last
case fails the test.

On Sat, 1 Feb 2020 at 13:42, Ronaldo Persiano <

rcmpersiano@

> wrote:

The C-like for has the following general form:

[for( initialization;
test;
iteration ) output ]

The output is done always after each test and the for escape just after
the test before the output. So, a better understanding of the control
structure is grasped by:

[ for( i = 0,
initialization;

  i < 8;

    (output(i))

    i = i+1,

    iteration ) ]

where I suppose a simple iteration and test. In above example, we will
have 8 outputs and 8 iterations besides the initialization. However, the
last iteration does not produces any output. When the iterations include
very demanding processes or illegal operations firing warnings we need to
do tests in the iteration steps in order to avoid them.

All that could be avoided if the output was done always before the test.


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

I would love comma separated subexpressions in the conditional. Because otherwise, I end up with things like: faces = [ for( first = true, finishing = false, finished = false, plen1 = len(prof1), plen2 = len(prof2), i=0, j=0, side=0; !finished; [INSERT CALCULATIONS HERE] face = [p1, p3, p2], i = i + (side? 1 : 0), j = j + (side? 0 : 1), first = false, finished = finishing, finishing = i>=plen1 && j>=plen2 ) if (!first) face ] - Revar > On Feb 1, 2020, at 7:07 AM, nop head <nop.head@gmail.com> wrote: > > Perhaps to fix Ronaldo's issue allow comma separated expressions in the test part that only get executed if the test passes, before the output. > > > > On Sat, 1 Feb 2020 at 14:50, adrianv <avm4@cornell.edu <mailto:avm4@cornell.edu>> wrote: > Well....kind of. The attraction of this loop structure is that you can > assign and reassign variables in the iteration part. And while it may look > C-like, OpenSCAD is not C. In OpenSCAD the loop body isn't "executed" it is > output. In C you would actually do your computations in the output part at > the end. But the whole reason to use this structure in OpenSCAD is so you > can reassign variables. This means the computation all happens in the > iteration block. Here's a simple example: > > // Produces length n vector counting from 0 > function example(n) = > [each // Needed to avoid singleton list output > for(output=[], i=0; > i<=n; > output=concat(output,[i]), // Here's the computation! > i=i+1, > dummy=echo(i=i,output=output)) > if (i==n) output // Output only in the last iteration > ]; > > Note how I can repeatedly add to the output variable without the need for > recursion? So there are two potential issues. One issue is in getting the > answer out. Here you see I need an "if" to output the answer when the > computation is done with a duplicated test for loop termination, which is > easy to detect since the termination test is very simple in this case. The > second issue as Rinaldo notes is that the iteration block runs an extra > time---it must run when i=n even though I don't want output for this case. > So this can produce an error, or it can waste time. > > So running echo(example(4)) produces: > > ECHO: i = 1, output = [0] > ECHO: i = 2, output = [0, 1] > ECHO: i = 3, output = [0, 1, 2] > ECHO: i = 4, output = [0, 1, 2, 3] > ECHO: i = 5, output = [0, 1, 2, 3, 4] > ECHO: [0, 1, 2, 3] > > > nophead wrote > > Isn't it exactly the same as C? The iteration part is done after the loop > > body is executed and the test is done before it. > > > > E.g. > > initialisation; > > while(test) { > > .... > > iteration; > > } > > > > So iteration is executed the same number of times as the body and the last > > case fails the test. > > > > On Sat, 1 Feb 2020 at 13:42, Ronaldo Persiano &lt; > > > rcmpersiano@ > > > &gt; wrote: > > > >> The C-like for has the following general form: > >> > >> [for( initialization; > >> test; > >> iteration ) output ] > >> > >> > >> The output is done always after each test and the for escape just after > >> the test before the output. So, a better understanding of the control > >> structure is grasped by: > >> > >> [ for( i = 0, > >> initialization; > >> > >> i < 8; > >> > >> (output(i)) > >> > >> i = i+1, > >> > >> iteration ) ] > >> > >> > >> where I suppose a simple iteration and test. In above example, we will > >> have 8 outputs and 8 iterations besides the initialization. However, the > >> last iteration does not produces any output. When the iterations include > >> very demanding processes or illegal operations firing warnings we need to > >> do tests in the iteration steps in order to avoid them. > >> > >> All that could be avoided if the output was done always before the test. > >> _______________________________________________ > >> OpenSCAD mailing list > >> > > > Discuss@.openscad > > >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org <http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org> > >> > > > > _______________________________________________ > > OpenSCAD mailing list > > > Discuss@.openscad > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org <http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org> > > > > > > -- > Sent from: http://forum.openscad.org/ <http://forum.openscad.org/> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org <http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org