discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

inconsistent propagation of $fa

A
adrianv
Fri, Jun 19, 2020 12:30 PM

function test() =
echo($fn=$fn, $fa=$fa, $fs=$fs)
[[0,0],[1,0],[1,1],[0,1]];

A=test();
polygon(test(),$fa=0.1,$fs=0.1);
c=test($fa=0.1,$fs=0.1);
d=test($fa=0.1,$fs=0.1);

Output is:

ECHO: $fn = 0, $fa = 12, $fs = 2    // starting value
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct
ECHO: $fn = 0, $fa = 12, $fs = 0.1  // wrong

If I delete one the last line then I get this:

ECHO: $fn = 0, $fa = 12, $fs = 2
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1
ECHO: $fn = 0, $fa = 12, $fs = 0.1

and if I delete one more last line I get this:

ECHO: $fn = 0, $fa = 12, $fs = 2
ECHO: $fn = 0, $fa = 12, $fs = 0.1

If I set $fa only without also setting $fs then it works correctly.  What's
going on here?

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

function test() = echo($fn=$fn, $fa=$fa, $fs=$fs) [[0,0],[1,0],[1,1],[0,1]]; A=test(); polygon(test(),$fa=0.1,$fs=0.1); c=test($fa=0.1,$fs=0.1); d=test($fa=0.1,$fs=0.1); Output is: ECHO: $fn = 0, $fa = 12, $fs = 2 // starting value ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct ECHO: $fn = 0, $fa = 12, $fs = 0.1 // wrong If I delete one the last line then I get this: ECHO: $fn = 0, $fa = 12, $fs = 2 ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 ECHO: $fn = 0, $fa = 12, $fs = 0.1 and if I delete one more last line I get this: ECHO: $fn = 0, $fa = 12, $fs = 2 ECHO: $fn = 0, $fa = 12, $fs = 0.1 If I set $fa only without also setting $fs then it works correctly. What's going on here? -- Sent from: http://forum.openscad.org/
NH
nop head
Fri, Jun 19, 2020 12:39 PM

I think the expressions are all evaluated and the expression version of
echo before any modules are instantiated. The last echo is always the one
in the polygon call.

On Fri, 19 Jun 2020 at 13:31, adrianv avm4@cornell.edu wrote:

function test() =
echo($fn=$fn, $fa=$fa, $fs=$fs)
[[0,0],[1,0],[1,1],[0,1]];

A=test();
polygon(test(),$fa=0.1,$fs=0.1);
c=test($fa=0.1,$fs=0.1);
d=test($fa=0.1,$fs=0.1);

Output is:

ECHO: $fn = 0, $fa = 12, $fs = 2    // starting value
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct
ECHO: $fn = 0, $fa = 12, $fs = 0.1  // wrong

If I delete one the last line then I get this:

ECHO: $fn = 0, $fa = 12, $fs = 2
ECHO: $fn = 0, $fa = 0.1, $fs = 0.1
ECHO: $fn = 0, $fa = 12, $fs = 0.1

and if I delete one more last line I get this:

ECHO: $fn = 0, $fa = 12, $fs = 2
ECHO: $fn = 0, $fa = 12, $fs = 0.1

If I set $fa only without also setting $fs then it works correctly.  What's
going on here?

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


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I think the expressions are all evaluated and the expression version of echo before any modules are instantiated. The last echo is always the one in the polygon call. On Fri, 19 Jun 2020 at 13:31, adrianv <avm4@cornell.edu> wrote: > function test() = > echo($fn=$fn, $fa=$fa, $fs=$fs) > [[0,0],[1,0],[1,1],[0,1]]; > > A=test(); > polygon(test(),$fa=0.1,$fs=0.1); > c=test($fa=0.1,$fs=0.1); > d=test($fa=0.1,$fs=0.1); > > Output is: > > ECHO: $fn = 0, $fa = 12, $fs = 2 // starting value > ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct > ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 // correct > ECHO: $fn = 0, $fa = 12, $fs = 0.1 // wrong > > If I delete one the last line then I get this: > > ECHO: $fn = 0, $fa = 12, $fs = 2 > ECHO: $fn = 0, $fa = 0.1, $fs = 0.1 > ECHO: $fn = 0, $fa = 12, $fs = 0.1 > > and if I delete one more last line I get this: > > ECHO: $fn = 0, $fa = 12, $fs = 2 > ECHO: $fn = 0, $fa = 12, $fs = 0.1 > > If I set $fa only without also setting $fs then it works correctly. What's > going on here? > > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
JB
Jordan Brown
Fri, Jun 19, 2020 3:24 PM

On 6/19/2020 5:39 AM, nop head wrote:

I think the expressions are all evaluated and the expression version
of echo before any modules are instantiated. The last echo is always
the one in the polygon call.

Yes.  And that one gets the default values.  The values passed to
polygon() apply to polygon(), not to the functions elsewhere in its
arguments.

This is made clearer by putting a label on each call to test():

function test(s) =
  echo(s,$fn=$fn, $fa=$fa, $fs=$fs)
  [[0,0],[1,0],[1,1],[0,1]];

A=test("A");
polygon(test("B"),$fa=0.1,$fs=0.1);
c=test("C",$fa=0.1,$fs=0.1);
d=test("D",$fa=0.1,$fs=0.1);

where the output is

ECHO: "A", $fn = 0, $fa = 12, $fs = 2
ECHO: "C", $fn = 0, $fa = 0.1, $fs = 0.1
ECHO: "D", $fn = 0, $fa = 0.1, $fs = 0.1
ECHO: "B", $fn = 0, $fa = 12, $fs = 0.1

The order of execution in OpenSCAD is ... interesting.  Try to predict
what this will output... (actual output below)

echo("main 1");
a = echo("main 2");

module foo() {
    b = echo("foo 3");
    echo("foo 1");
    children(2);
    children(1);
    children(2);
    echo("foo 2");
    c = echo("foo 4");
}

foo() {
    d = echo("foo child assign 1");
    echo("child 0");
    echo("child 1");
    echo("child 2");
    e = echo("foo child assign 2");
}

echo("main 3");
b = echo("main 4");

Give up on trying to figure it out?  Don't have an OpenSCAD handy to
try?  Here it is:

ECHO: "main 2"
ECHO: "main 4"
ECHO: "main 1"
ECHO: "foo child assign 1"
ECHO: "foo child assign 2"
ECHO: "foo 3"
ECHO: "foo 4"
ECHO: "foo 1"
ECHO: "child 2"
ECHO: "child 1"
ECHO: "child 2"
ECHO: "foo 2"
ECHO: "main 3"

I think the rules are:

  • Do all of the assignments in the current block.
  • For each module invocation
    o Do all of the assignments in the invocation's child block.
    o Do all of the assignments in the module.
    o Execute each of the module invocations in module.
    + Execute modules from the invocation's child block when
    children() is executed.
On 6/19/2020 5:39 AM, nop head wrote: > I think the expressions are all evaluated and the expression version > of echo before any modules are instantiated. The last echo is always > the one in the polygon call. Yes.  And that one gets the default values.  The values passed to polygon() apply to polygon(), not to the functions elsewhere in its arguments. This is made clearer by putting a label on each call to test(): function test(s) = echo(s,$fn=$fn, $fa=$fa, $fs=$fs) [[0,0],[1,0],[1,1],[0,1]]; A=test("A"); polygon(test("B"),$fa=0.1,$fs=0.1); c=test("C",$fa=0.1,$fs=0.1); d=test("D",$fa=0.1,$fs=0.1); where the output is ECHO: "A", $fn = 0, $fa = 12, $fs = 2 ECHO: "C", $fn = 0, $fa = 0.1, $fs = 0.1 ECHO: "D", $fn = 0, $fa = 0.1, $fs = 0.1 ECHO: "B", $fn = 0, $fa = 12, $fs = 0.1 The order of execution in OpenSCAD is ... interesting.  Try to predict what this will output... (actual output below) echo("main 1"); a = echo("main 2"); module foo() { b = echo("foo 3"); echo("foo 1"); children(2); children(1); children(2); echo("foo 2"); c = echo("foo 4"); } foo() { d = echo("foo child assign 1"); echo("child 0"); echo("child 1"); echo("child 2"); e = echo("foo child assign 2"); } echo("main 3"); b = echo("main 4"); Give up on trying to figure it out?  Don't have an OpenSCAD handy to try?  Here it is: ECHO: "main 2" ECHO: "main 4" ECHO: "main 1" ECHO: "foo child assign 1" ECHO: "foo child assign 2" ECHO: "foo 3" ECHO: "foo 4" ECHO: "foo 1" ECHO: "child 2" ECHO: "child 1" ECHO: "child 2" ECHO: "foo 2" ECHO: "main 3" I think the rules are: * Do all of the assignments in the current block. * For each module invocation o Do all of the assignments in the invocation's child block. o Do all of the assignments in the module. o Execute each of the module invocations in module. + Execute modules from the invocation's child block when children() is executed.
A
adrianv
Fri, Jun 19, 2020 8:20 PM

This is the thing I was confused about and then trying to clarify with
echos...which apparently just added another layer of confusion.  But your
explanation doesn't seem to be right.  Also look closely at the "B" output.
It's the case where polygon() wraps the call to test, and in fact $fs does
propagate, but $fa does not.

My actual code looks like this:

polygon(round_corners(shape, radius = radii),$fn=64);

The round_corners call uses $fn, $fa and $fs.  When written as above the
rounded corners seem rounded as expected.  In other words, $fn=64 is
passed into round_corners, both verified by echo and also by observing the
corners I get.  If I change it to:

polygon(round_corners(shape, radius = radii));

then $fn prints as zero and I get very visibly different corners.  So the
$fn value is definitely propagating into round_corners.

I'm now unable to reproduce the problem I had earlier where $fn propagated
but $fs and $fa did not.  I'm also not getting the result below where the
"B" case is weird.  I'm getting both $fa and $fs propagating into test() in
that case.

I have to admit that I almost always write functions rather than modules in
OpenSCAD, and functions execute in order.  I've found that modules will
invalidate my error handling because of running stuff out of order.  Though
maybe this has been improved in a recent release?  (I'm running 2019.05.)

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

This is the thing I was confused about and then trying to clarify with echos...which apparently just added another layer of confusion. But your explanation doesn't seem to be right. Also look closely at the "B" output. It's the case where polygon() wraps the call to test, and in fact $fs *does* propagate, but $fa does not. My actual code looks like this: polygon(round_corners(shape, radius = radii),$fn=64); The round_corners call uses $fn, $fa and $fs. When written as above the rounded corners seem rounded as expected. In other words, $fn=64 *is* passed into round_corners, both verified by echo and also by observing the corners I get. If I change it to: polygon(round_corners(shape, radius = radii)); then $fn prints as zero and I get very visibly different corners. So the $fn value is definitely propagating into round_corners. I'm now unable to reproduce the problem I had earlier where $fn propagated but $fs and $fa did not. I'm also not getting the result below where the "B" case is weird. I'm getting both $fa and $fs propagating into test() in that case. I have to admit that I almost always write functions rather than modules in OpenSCAD, and functions execute in order. I've found that modules will invalidate my error handling because of running stuff out of order. Though maybe this has been improved in a recent release? (I'm running 2019.05.) -- Sent from: http://forum.openscad.org/
NH
nop head
Fri, Jun 19, 2020 8:36 PM

You are passing $fn to polygon, so I have no idea why it affects
round_corners, that would seem like a bug to me.

I would try let($fn = 64) polygon(round_corners(shape, radius = radii)); if
I didn't want to change $fn at the current scope.

On Fri, 19 Jun 2020 at 21:21, adrianv avm4@cornell.edu wrote:

This is the thing I was confused about and then trying to clarify with
echos...which apparently just added another layer of confusion.  But your
explanation doesn't seem to be right.  Also look closely at the "B"
output.
It's the case where polygon() wraps the call to test, and in fact $fs
does
propagate, but $fa does not.

My actual code looks like this:

polygon(round_corners(shape, radius = radii),$fn=64);

The round_corners call uses $fn, $fa and $fs.  When written as above the
rounded corners seem rounded as expected.  In other words, $fn=64 is
passed into round_corners, both verified by echo and also by observing the
corners I get.  If I change it to:

polygon(round_corners(shape, radius = radii));

then $fn prints as zero and I get very visibly different corners.  So the
$fn value is definitely propagating into round_corners.

I'm now unable to reproduce the problem I had earlier where $fn propagated
but $fs and $fa did not.  I'm also not getting the result below where the
"B" case is weird.  I'm getting both $fa and $fs propagating into test()
in
that case.

I have to admit that I almost always write functions rather than modules in
OpenSCAD, and functions execute in order.  I've found that modules will
invalidate my error handling because of running stuff out of order.  Though
maybe this has been improved in a recent release?  (I'm running 2019.05.)

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


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

You are passing $fn to polygon, so I have no idea why it affects round_corners, that would seem like a bug to me. I would try let($fn = 64) polygon(round_corners(shape, radius = radii)); if I didn't want to change $fn at the current scope. On Fri, 19 Jun 2020 at 21:21, adrianv <avm4@cornell.edu> wrote: > This is the thing I was confused about and then trying to clarify with > echos...which apparently just added another layer of confusion. But your > explanation doesn't seem to be right. Also look closely at the "B" > output. > It's the case where polygon() wraps the call to test, and in fact $fs > *does* > propagate, but $fa does not. > > My actual code looks like this: > > polygon(round_corners(shape, radius = radii),$fn=64); > > The round_corners call uses $fn, $fa and $fs. When written as above the > rounded corners seem rounded as expected. In other words, $fn=64 *is* > passed into round_corners, both verified by echo and also by observing the > corners I get. If I change it to: > > polygon(round_corners(shape, radius = radii)); > > then $fn prints as zero and I get very visibly different corners. So the > $fn value is definitely propagating into round_corners. > > I'm now unable to reproduce the problem I had earlier where $fn propagated > but $fs and $fa did not. I'm also not getting the result below where the > "B" case is weird. I'm getting both $fa and $fs propagating into test() > in > that case. > > I have to admit that I almost always write functions rather than modules in > OpenSCAD, and functions execute in order. I've found that modules will > invalidate my error handling because of running stuff out of order. Though > maybe this has been improved in a recent release? (I'm running 2019.05.) > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Fri, Jun 19, 2020 8:51 PM

I actually have no problem writing polygon(round_corners(shape, radius=radii,
$fn=64)) instead if that's what I need to do.  I wonder if there's some
weird indeterminate scoping going on.

nophead wrote

You are passing $fn to polygon, so I have no idea why it affects
round_corners, that would seem like a bug to me.

I would try let($fn = 64) polygon(round_corners(shape, radius = radii));
if
I didn't want to change $fn at the current scope.

I actually have no problem writing polygon(round_corners(shape, radius=radii, $fn=64)) instead if that's what I need to do. I wonder if there's some weird indeterminate scoping going on. nophead wrote > You are passing $fn to polygon, so I have no idea why it affects > round_corners, that would seem like a bug to me. > > I would try let($fn = 64) polygon(round_corners(shape, radius = radii)); > if > I didn't want to change $fn at the current scope. -- Sent from: http://forum.openscad.org/
AC
A. Craig West
Fri, Jun 19, 2020 9:00 PM

I suspect the argument list to the function is being considered to be
within the scope of the function when passing $ variables. Its not an
unreasonable interpretation

On Fri, 19 Jun 2020, 16:52 adrianv, avm4@cornell.edu wrote:

I actually have no problem writing polygon(round_corners(shape,
radius=radii,
$fn=64)) instead if that's what I need to do.  I wonder if there's some
weird indeterminate scoping going on.

nophead wrote

You are passing $fn to polygon, so I have no idea why it affects
round_corners, that would seem like a bug to me.

I would try let($fn = 64) polygon(round_corners(shape, radius = radii));
if
I didn't want to change $fn at the current scope.

I suspect the argument list to the function is being considered to be within the scope of the function when passing $ variables. Its not an unreasonable interpretation On Fri, 19 Jun 2020, 16:52 adrianv, <avm4@cornell.edu> wrote: > I actually have no problem writing polygon(round_corners(shape, > radius=radii, > $fn=64)) instead if that's what I need to do. I wonder if there's some > weird indeterminate scoping going on. > > > nophead wrote > > You are passing $fn to polygon, so I have no idea why it affects > > round_corners, that would seem like a bug to me. > > > > I would try let($fn = 64) polygon(round_corners(shape, radius = radii)); > > if > > I didn't want to change $fn at the current scope. > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Fri, Jun 19, 2020 9:06 PM

I thought of a use case that would rely on this behavior.  But if this is the
situation...why is the passing inconsistent?

acwest wrote

I suspect the argument list to the function is being considered to be
within the scope of the function when passing $ variables. Its not an
unreasonable interpretation

I thought of a use case that would rely on this behavior. But if this is the situation...why is the passing inconsistent? acwest wrote > I suspect the argument list to the function is being considered to be > within the scope of the function when passing $ variables. Its not an > unreasonable interpretation -- Sent from: http://forum.openscad.org/
JB
Jordan Brown
Fri, Jun 19, 2020 9:24 PM

On 6/19/2020 1:20 PM, adrianv wrote:

This is the thing I was confused about and then trying to clarify with
echos...which apparently just added another layer of confusion.  But your
explanation doesn't seem to be right.  Also look closely at the "B" output.
It's the case where polygon() wraps the call to test, and in fact $fs does
propagate, but $fa does not.

Ooh, yeah.  I hadn't noticed that.  It doesn't make any sense to me.

I have to admit that I almost always write functions rather than modules in
OpenSCAD, and functions execute in order.  I've found that modules will
invalidate my error handling because of running stuff out of order.  Though
maybe this has been improved in a recent release?  (I'm running 2019.05.)

Can you give examples of error handling that doesn't work right?

On 6/19/2020 2:00 PM, A. Craig West wrote:

I suspect the argument list to the function is being considered to be
within the scope of the function when passing $ variables. Its not an
unreasonable interpretation

Yeah, but that doesn't explain why $fs gets set but $fa does not.

My gut reaction is that the arguments shouldn't be able to interact with
one another, but as I think about it more I'm not sure.  $ variables are
kind of sort of global-ish, so maybe if you set them then they might
affect "peer" expressions, depend on the order of evaluation.  But I
think it would be cleaner if they did not interact.

On 6/19/2020 1:20 PM, adrianv wrote: > This is the thing I was confused about and then trying to clarify with > echos...which apparently just added another layer of confusion. But your > explanation doesn't seem to be right. Also look closely at the "B" output. > It's the case where polygon() wraps the call to test, and in fact $fs *does* > propagate, but $fa does not. Ooh, yeah.  I hadn't noticed that.  It doesn't make any sense to me. > I have to admit that I almost always write functions rather than modules in > OpenSCAD, and functions execute in order. I've found that modules will > invalidate my error handling because of running stuff out of order. Though > maybe this has been improved in a recent release? (I'm running 2019.05.) Can you give examples of error handling that doesn't work right? On 6/19/2020 2:00 PM, A. Craig West wrote: > I suspect the argument list to the function is being considered to be > within the scope of the function when passing $ variables. Its not an > unreasonable interpretation Yeah, but that doesn't explain why $fs gets set but $fa does not. My gut reaction is that the arguments shouldn't be able to interact with one another, but as I think about it more I'm not sure.  $ variables are kind of sort of global-ish, so maybe if you set them then they might affect "peer" expressions, depend on the order of evaluation.  But I think it would be cleaner if they did not interact.
HL
Hans L
Sat, Jun 20, 2020 11:43 PM

The answer is actually very simple.
Function or module arguments are not guaranteed to be evaluated in any
particular order

You write:  polygon(test(),$fa=0.1,$fs=0.1);
But, you seem to be expecting test() to be evaluated after assignment of
$fa and $fs, which to me is more bizarre than if they were actually done in
order.

The solution is to not write code where any one argument is dependent on
another from the same call being assigned first, and you'll not have any
problems.

The answer is actually very simple. Function or module arguments are not guaranteed to be evaluated in any particular order You write: polygon(test(),$fa=0.1,$fs=0.1); But, you seem to be expecting test() to be evaluated *after* assignment of $fa and $fs, which to me is more bizarre than if they were actually done in order. The solution is to not write code where any one argument is dependent on another from the same call being assigned first, and you'll not have any problems.