inconsistent propagation of $fa

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

inconsistent propagation of $fa

adrianv
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

nophead
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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

JordanBrown
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
    • Do all of the assignments in the invocation's child block.
    • Do all of the assignments in the module.
    • Execute each of the module invocations in module.
      • Execute modules from the invocation's child block when children() is executed.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

nophead
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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

acwest
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, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

JordanBrown
In reply to this post by adrianv
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.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

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


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

JordanBrown
On 6/20/2020 4:43 PM, Hans L wrote:
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.

My expectation was actually that the $fa and $fs assignments would not affect the test() invocation, no matter what order they were processed in, that they would affect *only* the polygon() invocation.

If you view the $ variables as being sort of like globals, that can affect the other arguments, then yes, order would matter.  But even then you'd expect it to be either left-to-right or right-to-left.  It might not be something you could rely on, but you'd expect that it would be one way or the other.  But it's not.

(And yes, of course you shouldn't do this in real life.  But it's still interesting to experiment with, to better understand what's happening.)

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

thehans
Also note that if you *do* require sequential assignment, that is specifically the purpose of  "let()".
It can be used either as a module or part of an expression.

On Sat, Jun 20, 2020 at 7:04 PM Jordan Brown <[hidden email]> wrote:
On 6/20/2020 4:43 PM, Hans L wrote:
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.

My expectation was actually that the $fa and $fs assignments would not affect the test() invocation, no matter what order they were processed in, that they would affect *only* the polygon() invocation.

If you view the $ variables as being sort of like globals, that can affect the other arguments, then yes, order would matter.  But even then you'd expect it to be either left-to-right or right-to-left.  It might not be something you could rely on, but you'd expect that it would be one way or the other.  But it's not.

(And yes, of course you shouldn't do this in real life.  But it's still interesting to experiment with, to better understand what's happening.)

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
Your explanation clarified everything for me.  Somehow I hadn't thought about
this as an order of evaluation issue.  It does mean it's a little clumsy to
propagate $ variables down into functions.  

Can you elaborate on what you said below?  Do you just mean that I can like
someone suggested earlier in the thread do this:

let($fa=0.1, $fs=0.1) polygon(test());  

Or is there some other thing you had in mind?  


thehans wrote
> Also note that if you *do* require sequential assignment, that is
> specifically the purpose of  "let()".
> It can be used either as a module or part of an expression.





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

thehans
> Can you elaborate on what you said below?

OK first, the general distinction between expressions/functions and modules:
   functions and expressions result in Values which can be assigned to variables.
   modules (wiki also generally calls these "statements" as opposed to "expressions") result in Geometry, which is sent to preview/render, but not assignable to variables*
      modules can also have "children", while expressions cannot.
*Not yet anyways, though it's been discussed as a possible future feature. 

Wiki references:

    "The parameters are evaluated sequentially and may depend on each other"

  "Sequential assignment of variables inside an expression"

There's even a section about using let() inside of list comprehensions, but I consider that more or less just another case of let as an expression:

Here's a modified example showing how one might user either, and how the sequence of assignment affects things:

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

// "let" as a module
// The thing after let(...) is a module: "polygon()", which is  a "child" of the let module.
let(
  pv1 = test("1"),
  $fa=0.1,
  $fs=0.1,
  pv2 = test("2")
) polygon(pv1);

// "let" as an expression:
// The thing after let(...) is an expression.
// Can be useful in defining "multi-line" functions.
function other_test() = let(
    pv1 = test("3"),
    $fa=0.1,
    $fs=0.1,
    pv2 = test("4")
 ) pv1;

echo(other_test());


On Sat, Jun 20, 2020 at 7:21 PM adrianv <[hidden email]> wrote:
Your explanation clarified everything for me.  Somehow I hadn't thought about
this as an order of evaluation issue.  It does mean it's a little clumsy to
propagate $ variables down into functions. 

Can you elaborate on what you said below?  Do you just mean that I can like
someone suggested earlier in the thread do this:

let($fa=0.1, $fs=0.1) polygon(test()); 

Or is there some other thing you had in mind? 


thehans wrote
> Also note that if you *do* require sequential assignment, that is
> specifically the purpose of  "let()".
> It can be used either as a module or part of an expression.





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

thehans
Also I should have probably been more clear that I meant "function calls" and "module instantiations" in the above explanation, to distinguish from the *definitions* of modules or functions.

The explanation gets slightly muddier still if you consider the experimental "function-literals" feature, where the function definition itself can be an expression.

On Sat, Jun 20, 2020 at 8:32 PM Hans L <[hidden email]> wrote:
> Can you elaborate on what you said below?

OK first, the general distinction between expressions/functions and modules:
   functions and expressions result in Values which can be assigned to variables.
   modules (wiki also generally calls these "statements" as opposed to "expressions") result in Geometry, which is sent to preview/render, but not assignable to variables*
      modules can also have "children", while expressions cannot.
*Not yet anyways, though it's been discussed as a possible future feature. 

Wiki references:

    "The parameters are evaluated sequentially and may depend on each other"

  "Sequential assignment of variables inside an expression"

There's even a section about using let() inside of list comprehensions, but I consider that more or less just another case of let as an expression:

Here's a modified example showing how one might user either, and how the sequence of assignment affects things:

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

// "let" as a module
// The thing after let(...) is a module: "polygon()", which is  a "child" of the let module.
let(
  pv1 = test("1"),
  $fa=0.1,
  $fs=0.1,
  pv2 = test("2")
) polygon(pv1);

// "let" as an expression:
// The thing after let(...) is an expression.
// Can be useful in defining "multi-line" functions.
function other_test() = let(
    pv1 = test("3"),
    $fa=0.1,
    $fs=0.1,
    pv2 = test("4")
 ) pv1;

echo(other_test());


On Sat, Jun 20, 2020 at 7:21 PM adrianv <[hidden email]> wrote:
Your explanation clarified everything for me.  Somehow I hadn't thought about
this as an order of evaluation issue.  It does mean it's a little clumsy to
propagate $ variables down into functions. 

Can you elaborate on what you said below?  Do you just mean that I can like
someone suggested earlier in the thread do this:

let($fa=0.1, $fs=0.1) polygon(test()); 

Or is there some other thing you had in mind? 


thehans wrote
> Also note that if you *do* require sequential assignment, that is
> specifically the purpose of  "let()".
> It can be used either as a module or part of an expression.





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
I've written thousands of lines of OpenSCAD code, so I've used let() plenty.
My problem was not understanding what let() does but muddy thinking about $
variables and what it means when you put a $ variable assignment into a
module or function argument.

I do feel concerned that the new function literals with no shorthand
mechanism for converting a function into a function literal mean that I'll
have to abandon using functions and use only function literals.   Either
that or use function literals sometimes and functions other times and it
will be confusing.  Or double-define anything you might want to use as an
argument as a function literal.   It seems a little bit of a mess.  


thehans wrote
> Also I should have probably been more clear that I meant "function calls"
> and "module instantiations" in the above explanation, to distinguish from
> the *definitions* of modules or functions.
>
> The explanation gets slightly muddier still if you consider the
> experimental "function-literals" feature, where the function
> definition itself can be an expression.
>
> On Sat, Jun 20, 2020 at 8:32 PM Hans L &lt;

> thehans@

> &gt; wrote:
>
>> > Can you elaborate on what you said below?
>>
>> OK first, the general distinction between expressions/functions and
>> modules:
>>    functions and expressions result in Values which can be assigned to
>> variables.
>>    modules (wiki also generally calls these "statements" as opposed to
>> "expressions") result in Geometry, which is sent to preview/render, but
>> not
>> assignable to variables*
>>       modules can also have "children", while expressions cannot.
>> *Not yet anyways, though it's been discussed as a possible future
>> feature.
>>
>> Wiki references:
>>
>> Let statement (aka module)
>> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Let_Statement
>>     "The parameters are evaluated sequentially and may depend on each
>> other"
>>
>> Let expression
>> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#let
>>   "Sequential assignment of variables inside an expression"
>>
>> There's even a section about using let() inside of list comprehensions,
>> but I consider that more or less just another case of let as an
>> expression:
>>
>> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#let_2
>>
>> Here's a modified example showing how one might user either, and how the
>> sequence of assignment affects things:
>>
>> function test(x) =
>>   echo(x,$fn=$fn, $fa=$fa, $fs=$fs)
>>   [[0,0],[1,0],[1,1],[0,1]];
>>
>> // "let" as a module
>> // The thing after let(...) is a module: "polygon()", which is  a "child"
>> of the let module.
>> let(
>>   pv1 = test("1"),
>>   $fa=0.1,
>>   $fs=0.1,
>>   pv2 = test("2")
>> ) polygon(pv1);
>>
>> // "let" as an expression:
>> // The thing after let(...) is an expression.
>> // Can be useful in defining "multi-line" functions.
>> function other_test() = let(
>>     pv1 = test("3"),
>>     $fa=0.1,
>>     $fs=0.1,
>>     pv2 = test("4")
>>  ) pv1;
>>
>> echo(other_test());
>>
>>
>> On Sat, Jun 20, 2020 at 7:21 PM adrianv &lt;

> avm4@

> &gt; wrote:
>>
>>> Your explanation clarified everything for me.  Somehow I hadn't thought
>>> about
>>> this as an order of evaluation issue.  It does mean it's a little clumsy
>>> to
>>> propagate $ variables down into functions.
>>>
>>> Can you elaborate on what you said below?  Do you just mean that I can
>>> like
>>> someone suggested earlier in the thread do this:
>>>
>>> let($fa=0.1, $fs=0.1) polygon(test());
>>>
>>> Or is there some other thing you had in mind?
>>>
>>>
>>> thehans wrote
>>> > Also note that if you *do* require sequential assignment, that is
>>> > specifically the purpose of  "let()".
>>> > It can be used either as a module or part of an expression.
>>>
>>>
>>>
>>>
>>>
>>> --
>>> Sent from: http://forum.openscad.org/
>>>
>>> _______________________________________________
>>> OpenSCAD mailing list
>>>

> Discuss@.openscad

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





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

Ronaldo
In reply to this post by thehans

Em dom., 21 de jun. de 2020 às 02:33, Hans L <[hidden email]> escreveu:
OK first, the general distinction between expressions/functions and modules:
   functions and expressions result in Values which can be assigned to variables.
   modules (wiki also generally calls these "statements" as opposed to "expressions") result in Geometry, which is sent to preview/render, but not assignable to variables*
      modules can also have "children", while expressions cannot.
*Not yet anyways, though it's been discussed as a possible future feature. 

Wiki references:

    "The parameters are evaluated sequentially and may depend on each other"

  "Sequential assignment of variables inside an expression"

There's even a section about using let() inside of list comprehensions, but I consider that more or less just another case of let as an expression:

There are use cases of assert that require a further explanation. 

 I usually write much more functions than modules and use assert in functions to check input data consistency. Typically :

function f(a) =
  assert( is_list(a) )
  let( b = len(a) )
  b;


That works fine. But if I write a module the similar way:

module t(a) {
  assert( is_list(a) );
  b = len(a);
  echo(b);
}
or even using it in a let like:

module t(a) {
  let(x = assert( is_list(a) )) { b = 0; echo(b=b); };
  b = len(a);
  echo(b2=b);
}

and call for instance t(1), I get :

WARNING: len() parameter could not be converted, in file , line 9

ERROR: Assertion '(is_list(a)))' failed in file , line 8

TRACE: called by 'assert', in file , line 8.

TRACE: called by 't', in file , line 13.


That means the system tried to assign len(a) to b *before* the assert is called.

To be sure the assert expression is evaluated before, I initialize something with the assert expression:

module t(a) {
  x = assert( is_list(a) );
  b = len(a);
  echo(b);
}
Is that correct? Is there any other alternative?

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
I asked about this behavior somewhat recently and was told that it had been
fixed in the latest OpenSCAD.  Conceivably modules could execute in blocks
so that nothing after an assert runs before the assert.  I haven't done
further investigations to see if the behavior has in fact changed.  With
random execution order, assertions are basically useless in modules.  

But I wonder how does assigning the assert to a variable force the assert to
run before the len evaluation in your example?  The two lines remain
independent.  It seems like you would need to do something like

x = assert(is_list(a)) 0;
b= x+len(a);

to ensure that the second line cannot run before the first one.  Of course
in this simple case one can do

b = assert(is_list(a)) len(b);

but this isn't always possible.  


Ronaldo wrote

> and call for instance t(1), I get :
>
> WARNING: len() parameter could not be converted, in file , line 9
>
> ERROR: Assertion '(is_list(a)))' failed in file , line 8
>
> TRACE: called by 'assert', in file , line 8.
>
> TRACE: called by 't', in file , line 13.
>
>
> That means the system tried to assign len(a) to b *before* the assert is
> called.
>
> To be sure the assert expression is evaluated before, I initialize
> something with the assert expression:
>
> module t(a) {
>   x = assert( is_list(a) );
>   b = len(a);
>   echo(b);
> }
>
> Is that correct? Is there any other alternative?
>
> _______________________________________________
> OpenSCAD mailing list

> Discuss@.openscad

> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

nophead
> But I wonder how does assigning the assert to a variable force the assert to run before the len evaluation in your example?

I think it is simply that expressions are evaluated before modules are instantiated, so the function version of assert runs before the module version, just as the function version of echo runs before the module version of echo.

The module version of assert doesn't make a lot of sense in this case where you want it to guard against an error in an expression, rather than just stopping broken geometry.


On Mon, 29 Jun 2020 at 19:53, adrianv <[hidden email]> wrote:
I asked about this behavior somewhat recently and was told that it had been
fixed in the latest OpenSCAD.  Conceivably modules could execute in blocks
so that nothing after an assert runs before the assert.  I haven't done
further investigations to see if the behavior has in fact changed.  With
random execution order, assertions are basically useless in modules. 

But I wonder how does assigning the assert to a variable force the assert to
run before the len evaluation in your example?  The two lines remain
independent.  It seems like you would need to do something like

x = assert(is_list(a)) 0;
b= x+len(a);

to ensure that the second line cannot run before the first one.  Of course
in this simple case one can do

b = assert(is_list(a)) len(b);

but this isn't always possible. 


Ronaldo wrote
> and call for instance t(1), I get :
>
> WARNING: len() parameter could not be converted, in file , line 9
>
> ERROR: Assertion '(is_list(a)))' failed in file , line 8
>
> TRACE: called by 'assert', in file , line 8.
>
> TRACE: called by 't', in file , line 13.
>
>
> That means the system tried to assign len(a) to b *before* the assert is
> called.
>
> To be sure the assert expression is evaluated before, I initialize
> something with the assert expression:
>
> module t(a) {
>   x = assert( is_list(a) );
>   b = len(a);
>   echo(b);
> }
>
> Is that correct? Is there any other alternative?
>
> _______________________________________________
> OpenSCAD mailing list

> Discuss@.openscad

> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: inconsistent propagation of $fa

adrianv
So is the order of evaluation of expressions at all limited, or it's
unspecified?  Do they execute in the order they appear in the code?  

In the example below, using an assignment means it's now an expression
evaluation instead of a module.  Does that guarantee that in the code

dummy = assert(is_list(a));
b=len(a);

that the first line is run first?  

It's hard for me to think of an example where you use assert and you want
the code after the assert to run, so the behavior of the assert module seems
to really limit its use.  




nophead wrote

>> But I wonder how does assigning the assert to a variable force the assert
> to run before the len evaluation in your example?
>
> I think it is simply that expressions are evaluated before modules are
> instantiated, so the function version of assert runs before the module
> version, just as the function version of echo runs before the module
> version of echo.
>
> The module version of assert doesn't make a lot of sense in this case
> where
> you want it to guard against an error in an expression, rather than just
> stopping broken geometry.
>
>
> On Mon, 29 Jun 2020 at 19:53, adrianv &lt;

> avm4@

> &gt; wrote:
>
>> I asked about this behavior somewhat recently and was told that it had
>> been
>> fixed in the latest OpenSCAD.  Conceivably modules could execute in
>> blocks
>> so that nothing after an assert runs before the assert.  I haven't done
>> further investigations to see if the behavior has in fact changed.  With
>> random execution order, assertions are basically useless in modules.
>>
>> But I wonder how does assigning the assert to a variable force the assert
>> to
>> run before the len evaluation in your example?  The two lines remain
>> independent.  It seems like you would need to do something like
>>
>> x = assert(is_list(a)) 0;
>> b= x+len(a);
>>
>> to ensure that the second line cannot run before the first one.  Of
>> course
>> in this simple case one can do
>>
>> b = assert(is_list(a)) len(b);
>>
>> but this isn't always possible.
>>
>>
>> Ronaldo wrote
>> > and call for instance t(1), I get :
>> >
>> > WARNING: len() parameter could not be converted, in file , line 9
>> >
>> > ERROR: Assertion '(is_list(a)))' failed in file , line 8
>> >
>> > TRACE: called by 'assert', in file , line 8.
>> >
>> > TRACE: called by 't', in file , line 13.
>> >
>> >
>> > That means the system tried to assign len(a) to b *before* the assert
>> is
>> > called.
>> >
>> > To be sure the assert expression is evaluated before, I initialize
>> > something with the assert expression:
>> >
>> > module t(a) {
>> >   x = assert( is_list(a) );
>> >   b = len(a);
>> >   echo(b);
>> > }
>> >
>> > Is that correct? Is there any other alternative?
>> >
>> > _______________________________________________
>> > OpenSCAD mailing list
>>
>> > Discuss@.openscad
>>
>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>>
>>
>>
>>
>>
>> --
>> Sent from: http://forum.openscad.org/
>>
>> _______________________________________________
>> OpenSCAD mailing list
>>

> Discuss@.openscad

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





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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
12