Hi all,
This produces the correct result, 'lilypads' at all 4 corners of an A3 sized
3D print.
for(i=[-0.5,0.5],j=[-0.5,0.5])
{
translate([297*i,420*j,0])
cylinder(0.2,15,15);
}
However this, which I tried first, did not work, and shows only 2 corners:
for(i=[-0.5,0.5])
{
translate([297*i,420*i,0])
cylinder(0.2,15,15);
}
Two things bug me:
I'm sure I used to be able to get away with the same variable twice.
I don't see what the problem is, as it's clearly recognised that
a. The x translation is moved by i * 297
b. The y translation is moved by i * 420
c. One disc is moved by both +ve values, the other by both -ve values
Version is 2019.05, on Windows 10.
Trying to answer my own question.
is it the case that OpenSCAD processes the contents of the braces twice:
once for the first value for 'i', -0.5, then again for the second value,
+0.5? And does not apply the other combination of cases that are valid?
Is this a behaviour that was changed at some point deliberately, or did I
imagine being able to get away with placing 4 corner pieces, or drilling 4
holes with just one for() variable?
Is there something I may have done subtly differently before to get the
result I was expecting with only one variable - or do I just need to always
define a second, to my mind redundant, variable?
Thanks for any illumination of this process!
Cheers,
Alex Gibson
admg consulting
edumaker limited
. Project management
. Operations & Process improvement
. 3D Printing
The for loop is iterating through a list with two elements, -0.5 and +0.5
so it will only create two objects, no matter what you do with the result.
Not sure why you would think otherwise. If you use i in both the x and y
expressions it has the same value for one iteration and the second value
for the other.
To make four holes with one loop perhaps you rotated by 90 degrees, or
indexed a table to get independent x and y values. The straight forward way
is to use two variables as your first example. It has always been like that.
On Thu, 18 Jun 2020 at 16:28, Alex Gibson alex@alexgibson.net wrote:
Hi all,
This produces the correct result, ‘lilypads’ at all 4 corners of an A3
sized 3D print.
for(i=[-0.5,0.5],j=[-0.5,0.5])
{
translate([297*i,420*j,0])
cylinder(0.2,15,15);
}
However this, which I tried first, did not work, and shows only 2 corners:
for(i=[-0.5,0.5])
{
translate([297*i,420*i,0])
cylinder(0.2,15,15);
}
Two things bug me:
I’m sure I used to be able to get away with the same variable
twice.
I don’t see what the problem is, as it’s clearly recognised that
a. The x translation is moved by i * 297
b. The y translation is moved by i * 420
c. One disc is moved by both +ve values, the other by both -ve
values
Version is 2019.05, on Windows 10.
Trying to answer my own question…
is it the case that OpenSCAD processes the contents of the braces twice:
once for the first value for ‘i’, -0.5, then again for the second value,
+0.5? And does not apply the other combination of cases that are valid?
Is this a behaviour that was changed at some point deliberately, or did I
imagine being able to get away with placing 4 corner pieces, or drilling 4
holes with just one for() variable?
Is there something I may have done subtly differently before to get the
result I was expecting with only one variable – or do I just need to always
define a second, to my mind redundant, variable?
Thanks for any illumination of this process!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Thanks Chris, so I’ve correctly understood what’s going on, but somehow must have a false memory of it ever working another way!
It’s quite possible I might have used a rotation. Will go back over some older code and see.
The ‘other way’ I imagined this could work is that for the contents of the braces, every time it gets to an instance of ‘i’, it could apply both (/all) values of ‘i’. This results in the grid of 4 possible outcomes.
At least I can now eliminate that from my thinking and that was the purpose of asking the question!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of nop head
Sent: 18 June 2020 16:48
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] Bug or my misunderstanding of 'for'?
The for loop is iterating through a list with two elements, -0.5 and +0.5 so it will only create two objects, no matter what you do with the result. Not sure why you would think otherwise. If you use i in both the x and y expressions it has the same value for one iteration and the second value for the other.
To make four holes with one loop perhaps you rotated by 90 degrees, or indexed a table to get independent x and y values. The straight forward way is to use two variables as your first example. It has always been like that.
On Thu, 18 Jun 2020 at 16:28, Alex Gibson alex@alexgibson.net wrote:
Hi all,
This produces the correct result, ‘lilypads’ at all 4 corners of an A3 sized 3D print.
for(i=[-0.5,0.5],j=[-0.5,0.5])
{
translate([297*i,420*j,0])
cylinder(0.2,15,15);
}
However this, which I tried first, did not work, and shows only 2 corners:
for(i=[-0.5,0.5])
{
translate([297*i,420*i,0])
cylinder(0.2,15,15);
}
Two things bug me:
I’m sure I used to be able to get away with the same variable twice.
I don’t see what the problem is, as it’s clearly recognised that
a. The x translation is moved by i * 297
b. The y translation is moved by i * 420
c. One disc is moved by both +ve values, the other by both -ve values
Version is 2019.05, on Windows 10.
Trying to answer my own question…
is it the case that OpenSCAD processes the contents of the braces twice: once for the first value for ‘i’, -0.5, then again for the second value, +0.5? And does not apply the other combination of cases that are valid?
Is this a behaviour that was changed at some point deliberately, or did I imagine being able to get away with placing 4 corner pieces, or drilling 4 holes with just one for() variable?
Is there something I may have done subtly differently before to get the result I was expecting with only one variable – or do I just need to always define a second, to my mind redundant, variable?
Thanks for any illumination of this process!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Virus-free. http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient www.avg.com
On 6/18/2020 9:07 AM, Alex Gibson wrote:
The ‘other way’ I imagined this could work is that for the
contents of the braces, every time it gets to an instance of ‘i’, it
could apply both (/all) values of ‘i’. This results in the grid of 4
possible outcomes.
That would yield some very peculiar results.
for (i = [1,2]) echo(i*2, i+i);
would yield, I think:
2, 2
2, 3
2, 3
2, 4
4, 2
4, 3
4, 3
4, 4
and of course the number of combinations would explode as the number of
values and the number of references increase.
I see!
So, while it might be useful and quicker in my use case, it could cause an unacceptable lack of constraint in others!
At the risk of putting my ignorance of programming languages formation on full display, but in the spirit of ‘don’t repeat yourself’, is there not a shorter way to use a globally defined range of numbers in a for() loop?
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (plus_minus_halves,one_two_three)
{
translate([20*plus_minus_halves,40*one_two_three,0])
cylinder(0.2,15,15);
}
…results in no movement – but also no error!
Whereas this works, and seems to be saying the same thing…
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (i=plus_minus_halves,j=one_two_three)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
You can even write the same thing as:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=j)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Is that just a case of ‘that’s the syntax’ or is there something that is usefully being done by forcing the for() loop to define the variables in what feels to me like a redundant way?
This is an odd (to me) case:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=i)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Results in:
…whereas…
india = [-0.5,0.5];
juliet = [1,2,3];
for (i=india,j=india)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Gives you..
So even though in the for() variable, we first say that i (within the for loop) is i (as defined earlier), saying j=i does not result in an output matching either instance???
I find that a bit odd. No doubt there is a sensible reason for this!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
From: Jordan Brown [mailto:openscad@jordan.maileater.net]
Sent: 18 June 2020 17:35
To: OpenSCAD general discussion; Alex Gibson
Subject: Re: [OpenSCAD] Bug or my misunderstanding of 'for'?
On 6/18/2020 9:07 AM, Alex Gibson wrote:
The ‘other way’ I imagined this could work is that for the contents of the braces, every time it gets to an instance of ‘i’, it could apply both (/all) values of ‘i’. This results in the grid of 4 possible outcomes.
That would yield some very peculiar results.
for (i = [1,2]) echo(i*2, i+i);
would yield, I think:
2, 2
2, 3
2, 3
2, 4
4, 2
4, 3
4, 3
4, 4
and of course the number of combinations would explode as the number of values and the number of references increase.
Virus-free. http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient www.avg.com
For your first version I get an error: WARNING: Unable to convert
translate([[-10, 10], [40, 80, 120], 0]) parameter to a vec3 or vec2 of
numbers, in file , line 11
I am surprised for without a variable doesn't give an error though. It
executes the loop but as there is no variable each iteration is identical.
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=i)
The j = i now refers to the variable i, not the list i.
On Thu, 18 Jun 2020 at 18:15, Alex Gibson alex@alexgibson.net wrote:
I see!
So, while it might be useful and quicker in my use case, it could cause an
unacceptable lack of constraint in others!
At the risk of putting my ignorance of programming languages formation on
full display, but in the spirit of ‘don’t repeat yourself’, is there not a
shorter way to use a globally defined range of numbers in a for() loop?
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (plus_minus_halves,one_two_three)
{*
translate([20*plus_minus_halves,40*one_two_three,0])*
cylinder(0.2,15,15);*
}*
…results in no movement – but also no error!
Whereas this works, and seems to be saying the same thing…
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (i=plus_minus_halves,j=one_two_three)
{*
translate([20*i,40*j,0])*
cylinder(0.2,5,5);*
}*
You can even write the same thing as:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=j)
{*
translate([20*i,40*j,0])*
cylinder(0.2,5,5);*
}*
Is that just a case of ‘that’s the syntax’ or is there something that is
usefully being done by forcing the for() loop to define the variables in
what feels to me like a redundant way?
This is an odd (to me) case:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=i)
{*
translate([20*i,40*j,0])*
cylinder(0.2,5,5);*
}*
Results in:
…whereas…
india = [-0.5,0.5];
juliet = [1,2,3];
for (i=india,j=india)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Gives you..
So even though in the for() variable, we first say that i (within the for
loop) is i (as defined earlier), saying j=i does not result in an output
matching either instance???
I find that a bit odd. No doubt there is a sensible reason for this!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
From: Jordan Brown [mailto:openscad@jordan.maileater.net]
Sent: 18 June 2020 17:35
To: OpenSCAD general discussion; Alex Gibson
Subject: Re: [OpenSCAD] Bug or my misunderstanding of 'for'?
On 6/18/2020 9:07 AM, Alex Gibson wrote:
The ‘other way’ I imagined this could work is that for the contents
of the braces, every time it gets to an instance of ‘i’, it could apply
both (/all) values of ‘i’. This results in the grid of 4 possible
outcomes.
That would yield some very peculiar results.
for (i = [1,2]) echo(i*2, i+i);
would yield, I think:
2, 2
2, 3
2, 3
2, 4
4, 2
4, 3
4, 3
4, 4
and of course the number of combinations would explode as the number of
values and the number of references increase.
Virus-free. www.avg.com
http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
On 6/18/2020 10:14 AM, Alex Gibson wrote:
So, while it might be useful and quicker in my use case, it could
cause an unacceptable lack of constraint in others!
More that in the general case it wouldn't be a useful interpretation.
At the risk of putting my ignorance of programming languages formation
on full display, but in the spirit of ‘don’t repeat yourself’, is
there not a shorter way to use a globally defined range of numbers in
a for() loop?
/ /
/plus_minus_halves = [-0.5,0.5];/
/one_two_three = [1,2,3];/
/ /
/for (plus_minus_halves,one_two_three)/
/ {/
/ translate([20plus_minus_halves,40one_two_three,0])/
/ cylinder(0.2,15,15);/
/ }/
/ /
…results in no movement – but also no error!
I suspect that it's an accident that that "for" is not considered to be
an error. What it seems to do is to iterate across the vector(s)
without assigning the values to any names.
In the translate, plus_minus_halves and one_two_three are still
vectors. Multiplying a vector by a number is allowed, but what you're
then passing to translate is a vector consisting of a two-entry vector,
a three-entry vector, and a zero. That's not a legal input for translate().
Whereas this works, and seems to be saying the same thing…
/plus_minus_halves = [-0.5,0.5];/
/one_two_three = [1,2,3];/
/ /
/for (i=plus_minus_halves,j=one_two_three)/
/ {/
/ translate([20i,40j,0])/
/ cylinder(0.2,5,5);/
/ }/
That assigns successive values from the vectors to i and j.
Considering the simpler case first:
v = [1,2,3];
for (i = v) {
echo(i);
}
evaluates the body once for each element in v, setting i equal to that
element. That is, the body is evaluated once with i=1, once with i=2,
and once with i=3.
A "for" with multiple values is treated like nested "for"s:
v1 = [1,2,3];
v2 = [4,5,6];
for (i = v1, j = v2) {
echo(i,j);
}
is the same as
v1 = [1,2,3];
v2 = [4,5,6];
for (i = v1) {
for (j = v2) {
echo(i,j);
}
}
except that the generated tree is subtly different. (You can't tell
unless you look at diagnostic information; it doesn't affect the model.)
You can even write the same thing as:
/i = [-0.5,0.5];/
/j = [1,2,3];/
/ /
/for (i=i,j=j)/
/ {/
/ translate([20i,40j,0])/
/ cylinder(0.2,5,5);/
/ }/
Is that just a case of ‘that’s the syntax’ or is there something that
is usefully being done by forcing the for() loop to define the
variables in what feels to me like a redundant way?
Here you're doing something that works, but can be confusing.
i and j are vectors of two and three elements, respectively.
The for loop walks across those two vectors as in the previous examples,
assigning the individual values to new i and j. Those new i and j
"hide" the i and j defined earlier.
This is an odd (to me) case:
/i = [-0.5,0.5];/
/j = [1,2,3];/
/ /
/for (i=i,j=i)/
/ {/
/ translate([20i,40j,0])/
/ cylinder(0.2,5,5);/
/ }/
The same sort of thing is happening, but we need to look at it even more
carefully.
i and j start out as the two vectors.
Then a new i is created to step across the old i.
Then a new j is created to step across ... the new i. By the time that
the j=i is examined, the original "i" containing a vector is no longer
visible; what is visible is the current value of i as we step along the
vector.
Mostly, just don't do this kind of thing. It will hurt your brain.
india = [-0.5,0.5];
juliet = [1,2,3];
for (i=india,j=india)
{
translate([20i,40j,0])
cylinder(0.2,5,5);
}
Right. Because nothing is replacing "india". i steps across india (a
vector of two elements), and for each of those elements j steps across
india. (Note that nothing looks at juliet.)
So even though in the for() variable, we first say that i (within the
for loop) is i (as defined earlier), saying j=i does not result in an
output matching either instance???
I find that a bit odd. No doubt there is a sensible reason for this!
It's all about exactly what happens to the names, in exactly what order.
99% of the answer is "don't assign to a name that's defined in a
higher-level block".
Thanks all for your input.
It seems that having been successfully using for() loops for a long while I had reasonably understood what was actually going on, but was chasing a mirage in terms of shortcuts to writing these for() loops.
This has really helped to de-clutter my understanding and get a more solid idea of the mechanics ‘under the bonnet’ of OpenSCAD and why it behaves as it does. Hope it’s not cluttered your brains too much!
So I will just accept that for() can’t immediately use a pre-defined list, but can take it and assign it to a value. This is still a small benefit to me as I need to run for() over a specific list of values quite often, I can create a named list for the cleanest possible DRY code!
Cheers,
Alex Gibson
admg consulting
edumaker limited
· Project management
· Operations & Process improvement
· 3D Printing
From: Jordan Brown [mailto:openscad@jordan.maileater.net]
Sent: 18 June 2020 23:23
To: Alex Gibson; 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Bug or my misunderstanding of 'for'?
On 6/18/2020 10:14 AM, Alex Gibson wrote:
So, while it might be useful and quicker in my use case, it could cause an unacceptable lack of constraint in others!
More that in the general case it wouldn't be a useful interpretation.
At the risk of putting my ignorance of programming languages formation on full display, but in the spirit of ‘don’t repeat yourself’, is there not a shorter way to use a globally defined range of numbers in a for() loop?
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (plus_minus_halves,one_two_three)
{
translate([20*plus_minus_halves,40*one_two_three,0])
cylinder(0.2,15,15);
}
…results in no movement – but also no error!
I suspect that it's an accident that that "for" is not considered to be an error. What it seems to do is to iterate across the vector(s) without assigning the values to any names.
In the translate, plus_minus_halves and one_two_three are still vectors. Multiplying a vector by a number is allowed, but what you're then passing to translate is a vector consisting of a two-entry vector, a three-entry vector, and a zero. That's not a legal input for translate().
Whereas this works, and seems to be saying the same thing…
plus_minus_halves = [-0.5,0.5];
one_two_three = [1,2,3];
for (i=plus_minus_halves,j=one_two_three)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
That assigns successive values from the vectors to i and j.
Considering the simpler case first:
v = [1,2,3];
for (i = v) {
echo(i);
}
evaluates the body once for each element in v, setting i equal to that element. That is, the body is evaluated once with i=1, once with i=2, and once with i=3.
A "for" with multiple values is treated like nested "for"s:
v1 = [1,2,3];
v2 = [4,5,6];
for (i = v1, j = v2) {
echo(i,j);
}
is the same as
v1 = [1,2,3];
v2 = [4,5,6];
for (i = v1) {
for (j = v2) {
echo(i,j);
}
}
except that the generated tree is subtly different. (You can't tell unless you look at diagnostic information; it doesn't affect the model.)
You can even write the same thing as:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=j)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Is that just a case of ‘that’s the syntax’ or is there something that is usefully being done by forcing the for() loop to define the variables in what feels to me like a redundant way?
Here you're doing something that works, but can be confusing.
i and j are vectors of two and three elements, respectively.
The for loop walks across those two vectors as in the previous examples, assigning the individual values to new i and j. Those new i and j "hide" the i and j defined earlier.
This is an odd (to me) case:
i = [-0.5,0.5];
j = [1,2,3];
for (i=i,j=i)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
The same sort of thing is happening, but we need to look at it even more carefully.
i and j start out as the two vectors.
Then a new i is created to step across the old i.
Then a new j is created to step across ... the new i. By the time that the j=i is examined, the original "i" containing a vector is no longer visible; what is visible is the current value of i as we step along the vector.
Mostly, just don't do this kind of thing. It will hurt your brain.
india = [-0.5,0.5];
juliet = [1,2,3];
for (i=india,j=india)
{
translate([20*i,40*j,0])
cylinder(0.2,5,5);
}
Right. Because nothing is replacing "india". i steps across india (a vector of two elements), and for each of those elements j steps across india. (Note that nothing looks at juliet.)
So even though in the for() variable, we first say that i (within the for loop) is i (as defined earlier), saying j=i does not result in an output matching either instance???
I find that a bit odd. No doubt there is a sensible reason for this!
It's all about exactly what happens to the names, in exactly what order.
99% of the answer is "don't assign to a name that's defined in a higher-level block".
Virus-free. http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient www.avg.com