discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

feedback: let, echo and assert in expressions

DM
doug moen
Tue, Nov 15, 2016 4:00 PM

The current snapshot of OpenSCAD supports let, echo and assert in
expressions. The latter two are experimental features. I want to provide
some feedback about those features before the release.

I'm not happy about the different coding style that you have to use for
writing functions vs writing modules. I don't like the lack of consistency.
Also, the module idioms are better, easier to use than the idioms we are
now introducing for writing functions. I'd like to suggest an alternative.

We'll start with local definitions. In a module, you introduce local
definitions like this:
module m(x) {
a = ...;
b = ...;
code...
}
This used to be done using assign, but that's deprecated because the new
syntax is better.

In a function, you introduce local definitions like this:
function f(x) =
let (a = ...,
b = ...)
code;

The function idiom is basically the same as assign, which was deprecated
in favour of the new better syntax. I don't have a problem with let, it
is actually convenient and looks good in some contexts, but it's
inconsistent that you are forced to write modules and functions
differently, and that bugs me.

Now consider echo and assert. The syntax is again different between
modules and functions. That's because, in an expression, echo and
assert have an extra trailing argument which is the expression to
evaluate once the action has been taken.

module m(x) {
echo("m: x=",x);
a = ...;
b = ...;
code...
}
function f(x) =
echo("f: x=",x)
let (a = ...,
b = ...)
code;

Now suppose that I want a conditional echo. I don't want to trace every
call to the module/function, only certain special calls for some edge
condition.

For the module, that's easy:
module m(x) {
if (x < 0) echo("m: x=",x);
a = ...;
b = ...;
code...
}

For the function, it's possible, but it's an intellectual challenge to
figure out how to do it, and it's definitely ugly. This is the point where
the inconsistency between modules and functions blows up and becomes ugly
for me.

So I have an alternative suggestion. I want to introduce a new kind of
expression, called a 'qualified expression'. It consists of

  • '('
  • a sequence of one or more 'statements', each terminated by ';'.
  • an expression, which is evaluated to produce the result
  • ')'

A 'statement', in this context, is either a definition (like 'x=0') or an
action (like echo() or assert()). An action can be made conditional, or you
can put an action in the body of a 'for' loop. (In my implementation, I'm
actually reusing the code for 'if' and 'for' that's used in list
comprehensions, because it's the same syntax with just a different
interpretation.)

Here's how to write the function with a conditional echo, using this new
syntax:

function f(x) = (
if (x<0) echo("f: x=",x);
a = ...;
b = ...;
code
);

I'm interested if other people also think this is a good idea. I'm starting
to implement this in my OpenSCAD2 prototype. I'm far enough along that I
know this idea is coherent and implementable.

The current snapshot of OpenSCAD supports `let`, `echo` and `assert` in expressions. The latter two are experimental features. I want to provide some feedback about those features before the release. I'm not happy about the different coding style that you have to use for writing functions vs writing modules. I don't like the lack of consistency. Also, the module idioms are better, easier to use than the idioms we are now introducing for writing functions. I'd like to suggest an alternative. We'll start with local definitions. In a module, you introduce local definitions like this: module m(x) { a = ...; b = ...; code... } This used to be done using `assign`, but that's deprecated because the new syntax is better. In a function, you introduce local definitions like this: function f(x) = let (a = ..., b = ...) code; The function idiom is basically the same as `assign`, which was deprecated in favour of the new better syntax. I don't have a problem with `let`, it is actually convenient and looks good in some contexts, but it's inconsistent that you are forced to write modules and functions differently, and that bugs me. Now consider `echo` and `assert`. The syntax is again different between modules and functions. That's because, in an expression, `echo` and `assert` have an extra trailing argument which is the expression to evaluate once the action has been taken. module m(x) { echo("m: x=",x); a = ...; b = ...; code... } function f(x) = echo("f: x=",x) let (a = ..., b = ...) code; Now suppose that I want a conditional echo. I don't want to trace every call to the module/function, only certain special calls for some edge condition. For the module, that's easy: module m(x) { if (x < 0) echo("m: x=",x); a = ...; b = ...; code... } For the function, it's possible, but it's an intellectual challenge to figure out how to do it, and it's definitely ugly. This is the point where the inconsistency between modules and functions blows up and becomes ugly for me. So I have an alternative suggestion. I want to introduce a new kind of expression, called a 'qualified expression'. It consists of - '(' - a sequence of one or more 'statements', each terminated by ';'. - an expression, which is evaluated to produce the result - ')' A 'statement', in this context, is either a definition (like 'x=0') or an action (like echo() or assert()). An action can be made conditional, or you can put an action in the body of a 'for' loop. (In my implementation, I'm actually reusing the code for 'if' and 'for' that's used in list comprehensions, because it's the same syntax with just a different interpretation.) Here's how to write the function with a conditional echo, using this new syntax: function f(x) = ( if (x<0) echo("f: x=",x); a = ...; b = ...; code ); I'm interested if other people also think this is a good idea. I'm starting to implement this in my OpenSCAD2 prototype. I'm far enough along that I know this idea is coherent and implementable.
R
runsun
Tue, Nov 15, 2016 5:28 PM

That looks good to me. I assume that we can also do the conditional
assignment ?

function f(x, istrue) = (
istrue? (
a=...;
b=...;
echo("true");
)
: ( a = ... ;
b = ... ;
echo( "false");
);
echo("Done init");

code

);

and

function f(x, istrue) = (
istrue? (
a=...;
b=...;
echo("true");
)

code1

 : ( a = ... ;
     b = ... ;
     echo( "false");
   )
   

code2

);

Or your plan is to use if()/else like you suggested earlier in the other
thread:

function f(x, istrue) = (
if(istrue){
a=...;
b=...;
echo("true");
}
else {  a = ... ;
b = ... ;
echo( "false");
}
echo("Done init");

code

);

and

function f(x, istrue) = (
if(istrue){
a=...;
b=...;
echo("true");
}

code1

 else{ a = ... ;
         b = ... ;
         echo( "false");
      }
   

code2

);


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19112.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

That looks good to me. I assume that we can also do the conditional assignment ? > function f(x, istrue) = ( > istrue? ( > a=...; > b=...; > echo("true"); > ) > : ( a = ... ; > b = ... ; > echo( "false"); > ); > echo("Done init"); > * > code * > ); and > function f(x, istrue) = ( > istrue? ( > a=...; > b=...; > echo("true"); > ) > * > code1 * > : ( a = ... ; > b = ... ; > echo( "false"); > ) > * > code2 * > ); Or your plan is to use if()/else like you suggested earlier in the other thread: > function f(x, istrue) = ( > if(istrue){ > a=...; > b=...; > echo("true"); > } > else { a = ... ; > b = ... ; > echo( "false"); > } > echo("Done init"); > * > code * > ); and > function f(x, istrue) = ( > if(istrue){ > a=...; > b=...; > echo("true"); > } > * > code1 * > else{ a = ... ; > b = ... ; > echo( "false"); > } > * > code2 * > ); ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19112.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
runsun
Tue, Nov 15, 2016 5:32 PM

btw where is the assert() ? Produce "unknown module assert()" in the snapshot
I am using (2016.10.04 (git 7e0935d)), which I suppose is current ?


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19113.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

btw where is the assert() ? Produce "unknown module assert()" in the snapshot I am using (2016.10.04 (git 7e0935d)), which I suppose is current ? ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19113.html Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Tue, Nov 15, 2016 6:13 PM

I'm running 2016.11.06 and you have to enable 'assert' in the Features pane
before you can use it.

On 15 November 2016 at 12:32, runsun runsun@gmail.com wrote:

btw where is the assert() ? Produce "unknown module assert()" in the
snapshot
I am using (2016.10.04 (git 7e0935d)), which I suppose is current ?


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),
runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix (
2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid ,
animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont ,
tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg ,
tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19113.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

I'm running 2016.11.06 and you have to enable 'assert' in the Features pane before you can use it. On 15 November 2016 at 12:32, runsun <runsun@gmail.com> wrote: > btw where is the assert() ? Produce "unknown module assert()" in the > snapshot > I am using (2016.10.04 (git 7e0935d)), which I suppose is current ? > > > > ----- > > $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), > runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( > 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , > animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , > tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , > tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19113.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
DM
doug moen
Tue, Nov 15, 2016 6:48 PM

Hi Runsun.

You are right, we need a syntax for "compound actions" within a qualified
expression.

The syntax I'm using is:

if (istrue) (
                 a=...;
                 b=...;
                 echo("true");
              );

and you can also add an 'else' clause. Note the terminating ';'.

This defines a and b as local variables within the parentheses, the
variables aren't visible outside of that scope. Which is the way local
definitions work in the statement language as well, inside compound
statements.

Larger example:

function f(x, istrue) = (
if (istrue) (
a=...;
b=...;
echo("true");
)
else (  a = ... ;
b = ... ;
echo( "false");
);
echo("Done init");

code
);

Note that the compound actions are delimited by parentheses, not braces,
and the if-else expression is terminated with a ';'.

One reason I don't use { } braces for this syntax is that braces are
reserved for constructing record-like data structures in the OpenSCAD2
expression language, similar to JSON object literals, JavaScript object
literals, and Python dictionary literals. Whereas there is no conflict with
any other syntax if I use parentheses, and therefore I avoid ambiguity in
the grammar.

Another reason is that I'm using the same generalized grammar to parse both
list comprehensions and qualified expressions.

You can think of it like this: In the top-level and module statement
language, you use braces {} for grouping (compound statements), whereas in
the expression language and the list comprehension language, you use
parentheses for grouping (qualified expressions and compound actions).

On 15 November 2016 at 12:28, runsun runsun@gmail.com wrote:

That looks good to me. I assume that we can also do the conditional
assignment ?

function f(x, istrue) = (
istrue? (
a=...;
b=...;
echo("true");
)
: ( a = ... ;
b = ... ;
echo( "false");
);
echo("Done init");

code

);

and

function f(x, istrue) = (
istrue? (
a=...;
b=...;
echo("true");
)

code1

 : ( a = ... ;
     b = ... ;
     echo( "false");
   )

code2

);

Or your plan is to use if()/else like you suggested earlier in the other
thread:

function f(x, istrue) = (
if(istrue){
a=...;
b=...;
echo("true");
}
else {  a = ... ;
b = ... ;
echo( "false");
}
echo("Done init");

code

);

and

function f(x, istrue) = (
if(istrue){
a=...;
b=...;
echo("true");
}

code1

 else{ a = ... ;
         b = ... ;
         echo( "false");
      }

code2

);


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),
runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix (
2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid ,
animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont ,
tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg ,
tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19112.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Hi Runsun. You are right, we need a syntax for "compound actions" within a qualified expression. The syntax I'm using is: > if (istrue) ( > a=...; > b=...; > echo("true"); > ); and you can also add an 'else' clause. Note the terminating ';'. This defines a and b as local variables within the parentheses, the variables aren't visible outside of that scope. Which is the way local definitions work in the statement language as well, inside compound statements. Larger example: > function f(x, istrue) = ( > if (istrue) ( > a=...; > b=...; > echo("true"); > ) > else ( a = ... ; > b = ... ; > echo( "false"); > ); > echo("Done init"); > > code > ); Note that the compound actions are delimited by parentheses, not braces, and the if-else expression is terminated with a ';'. One reason I don't use { } braces for this syntax is that braces are reserved for constructing record-like data structures in the OpenSCAD2 expression language, similar to JSON object literals, JavaScript object literals, and Python dictionary literals. Whereas there is no conflict with any other syntax if I use parentheses, and therefore I avoid ambiguity in the grammar. Another reason is that I'm using the same generalized grammar to parse both list comprehensions and qualified expressions. You can think of it like this: In the top-level and module statement language, you use braces {} for grouping (compound statements), whereas in the expression language and the list comprehension language, you use parentheses for grouping (qualified expressions and compound actions). On 15 November 2016 at 12:28, runsun <runsun@gmail.com> wrote: > That looks good to me. I assume that we can also do the conditional > assignment ? > > > > function f(x, istrue) = ( > > istrue? ( > > a=...; > > b=...; > > echo("true"); > > ) > > : ( a = ... ; > > b = ... ; > > echo( "false"); > > ); > > echo("Done init"); > > > * > > code > * > > ); > > and > > > function f(x, istrue) = ( > > istrue? ( > > a=...; > > b=...; > > echo("true"); > > ) > > > * > > code1 > * > > : ( a = ... ; > > b = ... ; > > echo( "false"); > > ) > > > * > > code2 > * > > ); > > Or your plan is to use if()/else like you suggested earlier in the other > thread: > > > > function f(x, istrue) = ( > > if(istrue){ > > a=...; > > b=...; > > echo("true"); > > } > > else { a = ... ; > > b = ... ; > > echo( "false"); > > } > > echo("Done init"); > > > * > > code > * > > ); > > and > > > function f(x, istrue) = ( > > if(istrue){ > > a=...; > > b=...; > > echo("true"); > > } > > > * > > code1 > * > > else{ a = ... ; > > b = ... ; > > echo( "false"); > > } > > > * > > code2 > * > > ); > > > > > > ----- > > $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), > runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( > 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , > animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , > tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , > tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19112.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
R
runsun
Tue, Nov 15, 2016 8:37 PM

I see. If we go this way, we will have 3 different constructs for "if-else":

  1. In top-level and module:

    if(...) some_code_line;
    if(...){ } else { }

  2. In function:

    if(...) some_code_line;
    if(...)( ) else ( );

  3. In list comprehension:

    [ for(...) if(A) X ]
    [ for(...) if(A) X else Y ]
    [ for(...) if(A) if(B) X else Y ]
    [ for(...) if(A) ( if(B) X else Y ) ]
    [ for(...) if(A) ( if(B) X) else Y ]
    [ for(...) if(A) X else if(B) Y ]

Not sure about this, man. The inspiration of this change is that

"it's inconsistent that you are forced to write modules and functions
differently"

The intended change would mean that, in an attempt to solve that
inconsistency, we will create another inconsistency, while we are still
"forced to write modules and functions differently" (i.e., the problem isn't
actually solved), and this is on top of what already confusing usage of
if-else in the list comprehension.


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19117.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I see. If we go this way, we will have 3 different constructs for "if-else": 1) In top-level and module: if(...) some_code_line; if(...){ } else { } 2) In function: if(...) some_code_line; if(...)( ) else ( ); 3) In list comprehension: [ for(...) if(A) X ] [ for(...) if(A) X else Y ] [ for(...) if(A) if(B) X else Y ] [ for(...) if(A) ( if(B) X else Y ) ] [ for(...) if(A) ( if(B) X) else Y ] [ for(...) if(A) X else if(B) Y ] Not sure about this, man. The inspiration of this change is that "it's inconsistent that you are forced to write modules and functions differently" The intended change would mean that, in an attempt to solve that inconsistency, we will create another inconsistency, while we are still "forced to write modules and functions differently" (i.e., the problem isn't actually solved), and this is on top of what already confusing usage of if-else in the list comprehension. ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19117.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TP
Torsten Paul
Tue, Nov 15, 2016 8:58 PM

On 11/15/2016 06:32 PM, runsun wrote:

btw where is the assert() ? Produce "unknown module assert()"
in the snapshot I am using (2016.10.04 (git 7e0935d)), which
I suppose is current ?

Depends on the definition of current. This is still the latest
version linked on the download page, but there are some newer
builds in http://files.openscad.org/snapshots/ (Nov 11th) which
are not yet linked as I need to find some time to fix some
minor build issues.

Both assert() and the Customizer should be available in those
Nov 11 builds.

ciao,
Torsten.

On 11/15/2016 06:32 PM, runsun wrote: > btw where is the assert() ? Produce "unknown module assert()" > in the snapshot I am using (2016.10.04 (git 7e0935d)), which > I suppose is current ? > Depends on the definition of current. This is still the latest version linked on the download page, but there are some newer builds in http://files.openscad.org/snapshots/ (Nov 11th) which are not yet linked as I need to find some time to fix some minor build issues. Both assert() and the Customizer should be available in those Nov 11 builds. ciao, Torsten.
DM
doug moen
Tue, Nov 15, 2016 9:11 PM

Well, I'd like to be able to use if(c)a and if(c)a else b in every context
of a program where I need a conditional. I don't know why you claim this is
inconsistent and confusing.

In the grammar that I plan for OpenSCAD2 (with full backward
compatibility), there are two places in the grammar where if and if-else
occur. There is the statement grammar, and there is a generalized
expression grammar that includes expressions, list comprehensions and the
proposed "qualified expression" expression syntax. So it's not 3
constructs, its only 2. I'd prefer to get that down to a single if
construct, but that's not possible while preserving backwards compatibility.

The original problem that I proposed is, how do I add a conditional echo to
a function definition. If you have a less confusing and more consistent way
of writing that than what I proposed, I'd like to see it.

On 15 November 2016 at 15:37, runsun runsun@gmail.com wrote:

I see. If we go this way, we will have 3 different constructs for
"if-else":

  1. In top-level and module:

    if(...) some_code_line;
    if(...){ } else { }

  2. In function:

    if(...) some_code_line;
    if(...)( ) else ( );

  3. In list comprehension:

    [ for(...) if(A) X ]
    [ for(...) if(A) X else Y ]
    [ for(...) if(A) if(B) X else Y ]
    [ for(...) if(A) ( if(B) X else Y ) ]
    [ for(...) if(A) ( if(B) X) else Y ]
    [ for(...) if(A) X else if(B) Y ]

Not sure about this, man. The inspiration of this change is that

"it's inconsistent that you are forced to write modules and functions
differently"

The intended change would mean that, in an attempt to solve that
inconsistency, we will create another inconsistency, while we are still
"forced to write modules and functions differently" (i.e., the problem
isn't
actually solved), and this is on top of what already confusing usage of
if-else in the list comprehension.


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),
runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix (
2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid ,
animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont ,
tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg ,
tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19117.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Well, I'd like to be able to use if(c)a and if(c)a else b in every context of a program where I need a conditional. I don't know why you claim this is inconsistent and confusing. In the grammar that I plan for OpenSCAD2 (with full backward compatibility), there are two places in the grammar where if and if-else occur. There is the statement grammar, and there is a generalized expression grammar that includes expressions, list comprehensions and the proposed "qualified expression" expression syntax. So it's not 3 constructs, its only 2. I'd prefer to get that down to a single if construct, but that's not possible while preserving backwards compatibility. The original problem that I proposed is, how do I add a conditional echo to a function definition. If you have a less confusing and more consistent way of writing that than what I proposed, I'd like to see it. On 15 November 2016 at 15:37, runsun <runsun@gmail.com> wrote: > I see. If we go this way, we will have 3 different constructs for > "if-else": > > 1) In top-level and module: > > if(...) some_code_line; > if(...){ } else { } > > 2) In function: > > if(...) some_code_line; > if(...)( ) else ( ); > > 3) In list comprehension: > > [ for(...) if(A) X ] > [ for(...) if(A) X else Y ] > [ for(...) if(A) if(B) X else Y ] > [ for(...) if(A) ( if(B) X else Y ) ] > [ for(...) if(A) ( if(B) X) else Y ] > [ for(...) if(A) X else if(B) Y ] > > Not sure about this, man. The inspiration of this change is that > > "it's inconsistent that you are forced to write modules and functions > differently" > > The intended change would mean that, in an attempt to solve that > inconsistency, we will create another inconsistency, while we are still > "forced to write modules and functions differently" (i.e., the problem > isn't > actually solved), and this is on top of what already confusing usage of > if-else in the list comprehension. > > > > > > > ----- > > $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), > runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( > 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , > animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , > tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , > tests ( 2 ), text ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19117.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
P
Parkinbot
Tue, Nov 15, 2016 11:29 PM

I like all your propositions and never understood, why function and module
syntax could grow into such different fashions.

But let me remark, that using () for a function body will differ from {}
which is used for module bodies. Why not unify also this?

Is there any syntax planned for defining own operators? Something like:

K = L +_ M;
operator +_(L, M) = concat(L, M);

Another theme of course is operator overloading ... but I guess overloads
will have to wait for OpenSCAD3

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19126.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I like all your propositions and never understood, why function and module syntax could grow into such different fashions. But let me remark, that using *()* for a function body will differ from *{}* which is used for module bodies. Why not unify also this? Is there any syntax planned for defining own operators? Something like: > K = L +_ M; > operator +_(L, M) = concat(L, M); Another theme of course is operator overloading ... but I guess overloads will have to wait for OpenSCAD3 -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19126.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Wed, Nov 16, 2016 5:19 AM

On Nov 15, 2016, at 11:00, doug moen doug@moens.org wrote:
[…] So I have an alternative suggestion. I want to introduce a new kind of expression, called a 'qualified expression'. It consists of
• '('
• a sequence of one or more 'statements', each terminated by ';'.
• an expression, which is evaluated to produce the result
• ')'

I like this idea. (it’s also been on my mind for a while, inspired by how e.g. Scala does this).

I’m a bit uneasy about the parentheses vs. curly braces.
I see the syntax ambiguity being a potential issue. Some languages deal with that using extra syntax or an explicit return keyword.
A testable prototype would help though :)

I'm interested if other people also think this is a good idea. I'm starting to implement this in my OpenSCAD2 prototype. I'm far enough along that I know this idea is coherent and implementable.

That sounds like a good first step.

As I’ve mentioned earlier, I’d be interested in looking into swapping out the existing parser with a new one. Keeping compatibility while at the same time limiting how fast we can introduce new features makes this tricky. ..but if we continue our work on separating out the AST into a more well-defined API, it should make this easier.

-Marius

> On Nov 15, 2016, at 11:00, doug moen <doug@moens.org> wrote: > […] So I have an alternative suggestion. I want to introduce a new kind of expression, called a 'qualified expression'. It consists of > • '(' > • a sequence of one or more 'statements', each terminated by ';'. > • an expression, which is evaluated to produce the result > • ')' > I like this idea. (it’s also been on my mind for a while, inspired by how e.g. Scala does this). I’m a bit uneasy about the parentheses vs. curly braces. I see the syntax ambiguity being a potential issue. Some languages deal with that using extra syntax or an explicit return keyword. A testable prototype would help though :) > I'm interested if other people also think this is a good idea. I'm starting to implement this in my OpenSCAD2 prototype. I'm far enough along that I know this idea is coherent and implementable. That sounds like a good first step. As I’ve mentioned earlier, I’d be interested in looking into swapping out the existing parser with a new one. Keeping compatibility while at the same time limiting how fast we can introduce new features makes this tricky. ..but if we continue our work on separating out the AST into a more well-defined API, it should make this easier. -Marius
DM
doug moen
Wed, Nov 16, 2016 3:57 PM

Parkinbot said:

Is there any syntax planned for defining own operators?
Another theme of course is operator overloading

I don't personally feel the need for user defined operators. Functions are
good enough for me. I want to keep the language simple.

User defined operators can be quite complicated to implement, if you have
operator declarations that dynamically change the grammar. Then you no
longer have a context free grammar, you instead have to parse operator
declarations and feed grammar information back down to the lexical analyzer
and parser. We should avoid this.

Not all schemes for user defined infix operators require special operator
declarations or a dynamically changeable grammar. Look at Smalltalk, for
example.

In Haskell, you can turn any binary function into an infix operator using
backticks. The syntax
x f y
is equivalent to
f(x,y)
For example,
K = L concat M;
This is easy enough to implement. Would we really need anything more
complicated than this?

Operator overloading is a huge leap in complexity from defining new
operators. That presupposes the ability to define new user defined data
types. Do we really need this? Industrial strength data abstraction is a
can of worms that I don't want to open. For that, I feel it is better to
embed the OpenSCAD primitives in another programming language, via an
OpenSCAD library. Again, I want to keep the language simple.

Let me add this: I think that shapes should be values, and you should be
able to query the attributes of a shape, probably using dot notation. For
example, if you have a sphere, you should be able to ask for its radius.
And the same thing extends to user defined shapes: you should be able to
query the model parameters of any shape. Or query and operate on the
underlying geometry information. And I want to try implementing this in
OpenSCAD2.

Since I have professional experience as an object oriented programmer, the
"obvious" approach is to add object oriented programming and class
definitions to OpenSCAD. But I don't want to do this, because keep the
language simple. So I'm going to try to implement this idea in a really
simple way, without introducing user defined data types. That's the goal, I
won't start coding this until some time next year probably.

Parkinbot said: > Is there any syntax planned for defining own operators? > Another theme of course is operator overloading I don't personally feel the need for user defined operators. Functions are good enough for me. I want to keep the language simple. User defined operators can be quite complicated to implement, if you have operator declarations that dynamically change the grammar. Then you no longer have a context free grammar, you instead have to parse operator declarations and feed grammar information back down to the lexical analyzer and parser. We should avoid this. Not all schemes for user defined infix operators require special operator declarations or a dynamically changeable grammar. Look at Smalltalk, for example. In Haskell, you can turn any binary function into an infix operator using backticks. The syntax x `f` y is equivalent to f(x,y) For example, K = L `concat` M; This is easy enough to implement. Would we really need anything more complicated than this? Operator *overloading* is a huge leap in complexity from defining new operators. That presupposes the ability to define new user defined data types. Do we really need this? Industrial strength data abstraction is a can of worms that I don't want to open. For that, I feel it is better to embed the OpenSCAD primitives in another programming language, via an OpenSCAD library. Again, I want to keep the language simple. Let me add this: I think that shapes should be values, and you should be able to query the attributes of a shape, probably using dot notation. For example, if you have a sphere, you should be able to ask for its radius. And the same thing extends to user defined shapes: you should be able to query the model parameters of any shape. Or query and operate on the underlying geometry information. And I want to try implementing this in OpenSCAD2. Since I have professional experience as an object oriented programmer, the "obvious" approach is to add object oriented programming and class definitions to OpenSCAD. But I don't want to do this, because keep the language simple. So I'm going to try to implement this idea in a really simple way, without introducing user defined data types. That's the goal, I won't start coding this until some time next year probably.
DM
doug moen
Wed, Nov 16, 2016 4:50 PM

Parkinbot said:

But let me remark, that using () for a function body will differ from
{}
which is used for module bodies. Why not unify also this?

Marius said:

I’m a bit uneasy about the parentheses vs. curly braces.
I see the syntax ambiguity being a potential issue. Some languages deal
with that using extra syntax or an explicit return keyword.

In OpenSCAD2, functions and shapes are both first class values. Since
functions can take shapes as arguments and return them as results, the
current distinction between functions and modules ceases to make sense.
Functions can do everything that modules do. You can even use syntax like
'rotate(45) cube(10)' if 'rotate' and 'cube' are defined as functions. The
OpenSCAD2 design doc explains how this works in more detail, and I've
implemented the function part of this already.

So then it will become possible to stop using module definitions and write
all of your code using function definitions. So that's my eventual plan for
function/module unification. I don't want function definitions to be more
awkward to write than module definitions, and that partly motivates
"qualified expressions".

If my goal was to make OpenSCAD look more like C or Javascript, then I'd
probably implement Javascript style function definitions, like
function f(x) {
a = ...;
b = ...;
return result;
}
But if I wanted to write code like this, I'd switch to using OpenJsCAD.

My actual goals are different than this. I like the fact that OpenSCAD is a
purely declarative language. I want to move it more in the direction of a
pure expression language, where you eliminate the distinction between the
world of statements and the world of expressions, and where you can do
everything using expressions. (Marius mentioned Scala as an example of an
expression language; there are many others.) In an expression language, you
can introduce local variable definitions inside an expression, and that's
what let expressions and qualified expressions are for. In my version of
reality, function definitions are made purely of expressions, they don't
contain embedded statements (using our current statement grammar).

Right now, I'm trying to improve debuggability. I'm adding a breakpoint
action, for breaking into the debugger. I want to be able to insert
conditional breakpoints and conditional echo actions into any expression,
without the requirement to first break down complex expressions into a
sequence of variable assignments so that I can insert debug statements in
between the variable assignments, which I sometimes need to do in a
procedural language. So I need to extend qualified expressions so that they
can contain conditional and unconditional actions.

OpenSCAD2 has a fixed set of data types, based on JSON. What's missing,
that I've added, is a "record" data type. The current syntax is like this:
p = {x=1, y=2};
echo(p.x); // ECHO: 1
The basic use case is to represent a set of named model parameters. I also
intend to use this as the basis for JSON import/export.

Record literals are part of the reason I don't want to use curly braces for
compound actions inside of qualified expressions. The brace characters are
reserved for records.

Doug.

On 16 November 2016 at 00:19, Marius Kintel marius@kintel.net wrote:

On Nov 15, 2016, at 11:00, doug moen doug@moens.org wrote:
[…] So I have an alternative suggestion. I want to introduce a new kind

of expression, called a 'qualified expression'. It consists of

   • '('
   • a sequence of one or more 'statements', each terminated by ';'.
   • an expression, which is evaluated to produce the result
   • ')'

I like this idea. (it’s also been on my mind for a while, inspired by how
e.g. Scala does this).

I’m a bit uneasy about the parentheses vs. curly braces.
I see the syntax ambiguity being a potential issue. Some languages deal
with that using extra syntax or an explicit return keyword.
A testable prototype would help though :)

I'm interested if other people also think this is a good idea. I'm

starting to implement this in my OpenSCAD2 prototype. I'm far enough along
that I know this idea is coherent and implementable.

That sounds like a good first step.

As I’ve mentioned earlier, I’d be interested in looking into swapping out
the existing parser with a new one. Keeping compatibility while at the same
time limiting how fast we can introduce new features makes this tricky.
..but if we continue our work on separating out the AST into a more
well-defined API, it should make this easier.

-Marius


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

Parkinbot said: > But let me remark, that using *()* for a function body will differ from > *{}* > which is used for module bodies. Why not unify also this? Marius said: > > I’m a bit uneasy about the parentheses vs. curly braces. > I see the syntax ambiguity being a potential issue. Some languages deal > with that using extra syntax or an explicit return keyword. In OpenSCAD2, functions and shapes are both first class values. Since functions can take shapes as arguments and return them as results, the current distinction between functions and modules ceases to make sense. Functions can do everything that modules do. You can even use syntax like 'rotate(45) cube(10)' if 'rotate' and 'cube' are defined as functions. The OpenSCAD2 design doc explains how this works in more detail, and I've implemented the function part of this already. So then it will become possible to stop using module definitions and write all of your code using function definitions. So that's my eventual plan for function/module unification. I don't want function definitions to be more awkward to write than module definitions, and that partly motivates "qualified expressions". If my goal was to make OpenSCAD look more like C or Javascript, then I'd probably implement Javascript style function definitions, like function f(x) { a = ...; b = ...; return result; } But if I wanted to write code like this, I'd switch to using OpenJsCAD. My actual goals are different than this. I like the fact that OpenSCAD is a purely declarative language. I want to move it more in the direction of a pure expression language, where you eliminate the distinction between the world of statements and the world of expressions, and where you can do everything using expressions. (Marius mentioned Scala as an example of an expression language; there are many others.) In an expression language, you can introduce local variable definitions inside an expression, and that's what `let` expressions and qualified expressions are for. In my version of reality, function definitions are made purely of expressions, they don't contain embedded statements (using our current statement grammar). Right now, I'm trying to improve debuggability. I'm adding a `breakpoint` action, for breaking into the debugger. I want to be able to insert conditional breakpoints and conditional echo actions into any expression, without the requirement to first break down complex expressions into a sequence of variable assignments so that I can insert debug statements in between the variable assignments, which I sometimes need to do in a procedural language. So I need to extend qualified expressions so that they can contain conditional and unconditional actions. OpenSCAD2 has a fixed set of data types, based on JSON. What's missing, that I've added, is a "record" data type. The current syntax is like this: p = {x=1, y=2}; echo(p.x); // ECHO: 1 The basic use case is to represent a set of named model parameters. I also intend to use this as the basis for JSON import/export. Record literals are part of the reason I don't want to use curly braces for compound actions inside of qualified expressions. The brace characters are reserved for records. Doug. On 16 November 2016 at 00:19, Marius Kintel <marius@kintel.net> wrote: > > On Nov 15, 2016, at 11:00, doug moen <doug@moens.org> wrote: > > […] So I have an alternative suggestion. I want to introduce a new kind > of expression, called a 'qualified expression'. It consists of > > • '(' > > • a sequence of one or more 'statements', each terminated by ';'. > > • an expression, which is evaluated to produce the result > > • ')' > > > I like this idea. (it’s also been on my mind for a while, inspired by how > e.g. Scala does this). > > I’m a bit uneasy about the parentheses vs. curly braces. > I see the syntax ambiguity being a potential issue. Some languages deal > with that using extra syntax or an explicit return keyword. > A testable prototype would help though :) > > > I'm interested if other people also think this is a good idea. I'm > starting to implement this in my OpenSCAD2 prototype. I'm far enough along > that I know this idea is coherent and implementable. > > That sounds like a good first step. > > As I’ve mentioned earlier, I’d be interested in looking into swapping out > the existing parser with a new one. Keeping compatibility while at the same > time limiting how fast we can introduce new features makes this tricky. > ..but if we continue our work on separating out the AST into a more > well-defined API, it should make this easier. > > -Marius > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
P
Parkinbot
Wed, Nov 16, 2016 5:54 PM

doug.moen wrote

OpenSCAD2 has a fixed set of data types, based on JSON. What's missing,
that I've added, is a "record" data type. The current syntax is like this:
p = {x=1, y=2};
echo(p.x); // ECHO: 1
The basic use case is to represent a set of named model parameters. I also
intend to use this as the basis for JSON import/export.

Record literals are part of the reason I don't want to use curly braces
for
compound actions inside of qualified expressions. The brace characters are
reserved for records.

p = {x=1, y=2}; is a struct and p() = {whatever}; a function. A compiler
and a human can distinquish it.

To be honest, I still don't know which scope rules apply in OpenSCAD - is't
that a thing that is mainly connected with {} despite it gets changed with
every new release? And there is a lot of confusion going on having two
syntaxes for modules and functions. Why not confess that other languages
have solved this long time ago. Or is your final aim to get rid of modules?
Which would kick out the 95% of the users that don't write their own
functions.

Also, with OpenSCAD2 I would go so far to allow any module calls in
functions. Why? View them as debugging outputs like echo. But I guess,
again, there will be a scope or a bracket problem.

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19157.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > OpenSCAD2 has a fixed set of data types, based on JSON. What's missing, > that I've added, is a "record" data type. The current syntax is like this: > p = {x=1, y=2}; > echo(p.x); // ECHO: 1 > The basic use case is to represent a set of named model parameters. I also > intend to use this as the basis for JSON import/export. > > Record literals are part of the reason I don't want to use curly braces > for > compound actions inside of qualified expressions. The brace characters are > reserved for records. *p = {x=1, y=2};* is a struct and *p() = {whatever};* a function. A compiler and a human can distinquish it. To be honest, I still don't know which scope rules apply in OpenSCAD - is't that a thing that is mainly connected with *{}* despite it gets changed with every new release? And there is a lot of confusion going on having two syntaxes for modules and functions. Why not confess that other languages have solved this long time ago. Or is your final aim to get rid of modules? Which would kick out the 95% of the users that don't write their own functions. Also, with OpenSCAD2 I would go so far to allow any module calls in functions. Why? View them as debugging outputs like echo. But I guess, again, there will be a scope or a bracket problem. -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19157.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Wed, Nov 16, 2016 6:03 PM

It seems to me that OpenSCAD2 is totally hampering OpenSCAD development.
Not only do additions need to be backwards compatible with OpenSCAD they
now have to be forwards compatible with OpenSCAD2. That means a simple
thing like echo in functions that people have been asking for years never
gets implemented, even when there are perfectly good pull requests.
Meanwhile I waste time debugging functions on a daily basis although I have
no interest in OpenSCAD2.

On 16 November 2016 at 17:54, Parkinbot rudolf@parkinbot.com wrote:

doug.moen wrote

OpenSCAD2 has a fixed set of data types, based on JSON. What's missing,
that I've added, is a "record" data type. The current syntax is like

this:

p = {x=1, y=2};
echo(p.x); // ECHO: 1

The basic use case is to represent a set of named model parameters. I

also

intend to use this as the basis for JSON import/export.

Record literals are part of the reason I don't want to use curly braces
for
compound actions inside of qualified expressions. The brace characters

are

reserved for records.

p = {x=1, y=2}; is a struct and p() = {whatever}; a function. A
compiler
and a human can distinquish it.

To be honest, I still don't know which scope rules apply in OpenSCAD - is't
that a thing that is mainly connected with {} despite it gets changed
with
every new release? And there is a lot of confusion going on having two
syntaxes for modules and functions. Why not confess that other languages
have solved this long time ago. Or is your final aim to get rid of modules?
Which would kick out the 95% of the users that don't write their own
functions.

Also, with OpenSCAD2 I would go so far to allow any module calls in
functions. Why? View them as debugging outputs like echo. But I guess,
again, there will be a scope or a bracket problem.

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19157.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

It seems to me that OpenSCAD2 is totally hampering OpenSCAD development. Not only do additions need to be backwards compatible with OpenSCAD they now have to be forwards compatible with OpenSCAD2. That means a simple thing like echo in functions that people have been asking for years never gets implemented, even when there are perfectly good pull requests. Meanwhile I waste time debugging functions on a daily basis although I have no interest in OpenSCAD2. On 16 November 2016 at 17:54, Parkinbot <rudolf@parkinbot.com> wrote: > doug.moen wrote > > OpenSCAD2 has a fixed set of data types, based on JSON. What's missing, > > that I've added, is a "record" data type. The current syntax is like > this: > > p = {x=1, y=2}; > > echo(p.x); // ECHO: 1 > > The basic use case is to represent a set of named model parameters. I > also > > intend to use this as the basis for JSON import/export. > > > > Record literals are part of the reason I don't want to use curly braces > > for > > compound actions inside of qualified expressions. The brace characters > are > > reserved for records. > > *p = {x=1, y=2};* is a struct and *p() = {whatever};* a function. A > compiler > and a human can distinquish it. > > To be honest, I still don't know which scope rules apply in OpenSCAD - is't > that a thing that is mainly connected with *{}* despite it gets changed > with > every new release? And there is a lot of confusion going on having two > syntaxes for modules and functions. Why not confess that other languages > have solved this long time ago. Or is your final aim to get rid of modules? > Which would kick out the 95% of the users that don't write their own > functions. > > Also, with OpenSCAD2 I would go so far to allow any module calls in > functions. Why? View them as debugging outputs like echo. But I guess, > again, there will be a scope or a bracket problem. > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19157.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TP
Torsten Paul
Wed, Nov 16, 2016 6:45 PM

On 11/16/2016 07:03 PM, nop head wrote:

That means a simple thing like echo in functions that
people have been asking for years never gets implemented,
even when there are perfectly good pull requests.

This is merged now and I think the discussion did lead to
a more sensible and useful implementation.

The initial pull request was not perfectly good as it
did not even have a single test case, and those always
prove very important. The last delay for merging echo()
was actually an issue I've introduced when adding assert()
and missed a test for this specific case with vectors.
This affected echo() as well as both share some code.

There's quite a number of issues that are open for a
long time, but the reason for the delays is certainly
not the OpenSCAD2 discussion (which does seem to go off
at a tangent sometimes, but is very useful and important
in my opinion). The main issue (at least for me) is just
simple lack of time.

I think all those discussions about OpenSCAD2 are a
good thing, even if there's disagreements in some places.
In my opinion carrying over some ideas into current
OpenSCAD has improved todays application quite a bit.

ciao,
Torsten.

On 11/16/2016 07:03 PM, nop head wrote: > That means a simple thing like echo in functions that > people have been asking for years never gets implemented, > even when there are perfectly good pull requests. > This is merged now and I think the discussion did lead to a more sensible and useful implementation. The initial pull request was *not* perfectly good as it did not even have a single test case, and those always prove very important. The last delay for merging echo() was actually an issue I've introduced when adding assert() and missed a test for this specific case with vectors. This affected echo() as well as both share some code. There's quite a number of issues that are open for a long time, but the reason for the delays is certainly not the OpenSCAD2 discussion (which does seem to go off at a tangent sometimes, but is very useful and important in my opinion). The main issue (at least for me) is just simple lack of time. I think all those discussions about OpenSCAD2 are a good thing, even if there's disagreements in some places. In my opinion carrying over some ideas into current OpenSCAD has improved todays application quite a bit. ciao, Torsten.
MK
Marius Kintel
Wed, Nov 16, 2016 8:42 PM

On Nov 16, 2016, at 13:03, nop head nop.head@gmail.com wrote:

It seems to me that OpenSCAD2 is totally hampering OpenSCAD development.

What’s hampering OpenSCAD development is totally not OpenSCAD2, but the lack of good language design in the past, together with limited spare time among our very few developers. OpenSCAD2 is actually an attempt to avoid making grave language design mistakes by thinking ahead, and thus make OpenSCAD development easier in the future.

-Marius

> On Nov 16, 2016, at 13:03, nop head <nop.head@gmail.com> wrote: > > It seems to me that OpenSCAD2 is totally hampering OpenSCAD development. What’s hampering OpenSCAD development is totally not OpenSCAD2, but the lack of good language design in the past, together with limited spare time among our very few developers. OpenSCAD2 is actually an attempt to avoid making grave language design mistakes by thinking ahead, and thus make OpenSCAD development easier in the future. -Marius
RW
Rob Ward
Wed, Nov 16, 2016 9:00 PM

Agreed.  While most of the arguments/discussion in this thread and other
similar threads goes right over my head, I appreciate the point that
unless the base code and language concepts are cleaned up and
streamlined, then people who volunteer their time will have to "waste"
most of it just to accommodate the clever, but almost random (but
inspired!), features that have accumulated.  The fact that OpenSCAD is
as powerful and productive as it is, is a testimony to the creativity
and ability of all the people who have contributed, and they must be
congratulated, but unless some review is held that gives a more unified
approach, patches, upon patches, upon patches will just tire existing
people out and not encourage other new people to contribute.

Keep up the good work guys!

Rob

On 17/11/16 07:42, Marius Kintel wrote:

On Nov 16, 2016, at 13:03, nop head nop.head@gmail.com wrote:

It seems to me that OpenSCAD2 is totally hampering OpenSCAD development.

What’s hampering OpenSCAD development is totally not OpenSCAD2, but the lack of good language design in the past, together with limited spare time among our very few developers. OpenSCAD2 is actually an attempt to avoid making grave language design mistakes by thinking ahead, and thus make OpenSCAD development easier in the future.

-Marius


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

Agreed. While most of the arguments/discussion in this thread and other similar threads goes right over my head, I appreciate the point that unless the base code and language concepts are cleaned up and streamlined, then people who volunteer their time will have to "waste" most of it just to accommodate the clever, but almost random (but inspired!), features that have accumulated. The fact that OpenSCAD is as powerful and productive as it is, is a testimony to the creativity and ability of all the people who have contributed, and they must be congratulated, but unless some review is held that gives a more unified approach, patches, upon patches, upon patches will just tire existing people out and not encourage other new people to contribute. Keep up the good work guys! Rob On 17/11/16 07:42, Marius Kintel wrote: >> On Nov 16, 2016, at 13:03, nop head <nop.head@gmail.com> wrote: >> >> It seems to me that OpenSCAD2 is totally hampering OpenSCAD development. > What’s hampering OpenSCAD development is totally not OpenSCAD2, but the lack of good language design in the past, together with limited spare time among our very few developers. OpenSCAD2 is actually an attempt to avoid making grave language design mistakes by thinking ahead, and thus make OpenSCAD development easier in the future. > > -Marius > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
DM
doug moen
Thu, Nov 17, 2016 12:16 AM

Parkinbot said: "To be honest, I still don't know which scope rules apply
in OpenSCAD"

OpenSCAD doesn't have scope rules in the normal sense. Most programming
languages use 'lexical' or 'static' scoping. This means you can look at a
variable name at a particular point in the program and say, statically,
which variable definition it corresponds to (or say that the variable is
undefined at that point).

OpenSCAD uses some weird variant of dynamic scoping. The variable
definition that a given instance of a variable name refers to is determined
at run time, and can change dynamically during runtime. It doesn't work
like any other programming language, so in practice the behaviour is
unpredictable for normal users. You just have to run the program and see
what it does. The rules aren't documented and I've never been able to fully
figure them out. This also means I don't know how to compile OpenSCAD into
efficient code.

The OpenSCAD interpreter doesn't have a compile phase. It directly
interprets a parse tree. And that's what leads to the dynamic behaviour of
variable lookup.

In the research prototype that I am building, I have a compiler that looks
up every variable reference at compile time, using lexical scoping rules.
Variable references are converted into integer indexes into a stack frame.
At run time, the scope of a variable is fixed. That's how all modern
languages work. The interpreter runs faster, because indexing into a stack
frame is faster than looking up a string in a chain of symbol tables.

We could imagine using this kind of compiler technology in a future release
of OpenSCAD, where we impose lexical scoping rules, and compile OpenSCAD
into efficient code, maybe into fast parallel code that uses multiple cores
or runs on a GPU. But it wouldn't be fully backward compatible. And I don't
know what the lexical scoping rules should even be, since the current
behaviour is pretty random. I'd leave that decision to Marius and Torsten.

Here are some demos of weird variable lookup behaviour.

1    echo(a,b); // ECHO: 1,undef
2    b=a;
3    a=1;

The output is:
WARNING: Ignoring unknown variable 'a'
ECHO: 1,undef

When I first started using OpenSCAD, I assumed it was lexically scoped,
because that's how all languages work (I thought). Based on that
assumption, I deduced that the scope of 'a' is line 1, but not line 2. The
warning shows that 'a' is not in scope on line 2.

But that's the wrong way to think about OpenSCAD, because variables don't
have static scopes.

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

Look at line 4. In a lexically scoped language, the variable name 'a' would
statically refer to either the outer definition on line 1, or the inner
definition on line 6. One or the other. But you can't meaningfully ask
"what is the scope of 'a'" in OpenSCAD, because the choice is made at run
time, and changes dynamically. So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

Doug.

On 16 November 2016 at 12:54, Parkinbot rudolf@parkinbot.com wrote:

doug.moen wrote

OpenSCAD2 has a fixed set of data types, based on JSON. What's missing,
that I've added, is a "record" data type. The current syntax is like

this:

p = {x=1, y=2};
echo(p.x); // ECHO: 1

The basic use case is to represent a set of named model parameters. I

also

intend to use this as the basis for JSON import/export.

Record literals are part of the reason I don't want to use curly braces
for
compound actions inside of qualified expressions. The brace characters

are

reserved for records.

p = {x=1, y=2}; is a struct and p() = {whatever}; a function. A
compiler
and a human can distinquish it.

To be honest, I still don't know which scope rules apply in OpenSCAD - is't
that a thing that is mainly connected with {} despite it gets changed
with
every new release? And there is a lot of confusion going on having two
syntaxes for modules and functions. Why not confess that other languages
have solved this long time ago. Or is your final aim to get rid of modules?
Which would kick out the 95% of the users that don't write their own
functions.

Also, with OpenSCAD2 I would go so far to allow any module calls in
functions. Why? View them as debugging outputs like echo. But I guess,
again, there will be a scope or a bracket problem.

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19157.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Parkinbot said: "To be honest, I still don't know which scope rules apply in OpenSCAD" OpenSCAD doesn't have scope rules in the normal sense. Most programming languages use 'lexical' or 'static' scoping. This means you can look at a variable name at a particular point in the program and say, statically, which variable definition it corresponds to (or say that the variable is undefined at that point). OpenSCAD uses some weird variant of dynamic scoping. The variable definition that a given instance of a variable name refers to is determined at run time, and can change dynamically during runtime. It doesn't work like any other programming language, so in practice the behaviour is unpredictable for normal users. You just have to run the program and see what it does. The rules aren't documented and I've never been able to fully figure them out. This also means I don't know how to compile OpenSCAD into efficient code. The OpenSCAD interpreter doesn't have a compile phase. It directly interprets a parse tree. And that's what leads to the dynamic behaviour of variable lookup. In the research prototype that I am building, I have a compiler that looks up every variable reference at compile time, using lexical scoping rules. Variable references are converted into integer indexes into a stack frame. At run time, the scope of a variable is fixed. That's how all modern languages work. The interpreter runs faster, because indexing into a stack frame is faster than looking up a string in a chain of symbol tables. We could imagine using this kind of compiler technology in a future release of OpenSCAD, where we impose lexical scoping rules, and compile OpenSCAD into efficient code, maybe into fast parallel code that uses multiple cores or runs on a GPU. But it wouldn't be fully backward compatible. And I don't know what the lexical scoping rules should even be, since the current behaviour is pretty random. I'd leave that decision to Marius and Torsten. Here are some demos of weird variable lookup behaviour. 1 echo(a,b); // ECHO: 1,undef 2 b=a; 3 a=1; The output is: WARNING: Ignoring unknown variable 'a' ECHO: 1,undef When I first started using OpenSCAD, I assumed it was lexically scoped, because that's how all languages work (I thought). Based on that assumption, I deduced that the scope of 'a' is line 1, but not line 2. The warning shows that 'a' is not in scope on line 2. But that's the wrong way to think about OpenSCAD, because variables don't have static scopes. 1 a = 0; 2 module m() 3 { 4 function f() = a; 5 x = f(); 6 a = 1; 7 y = f(); 8 echo(x,y); 9 } 10 m(); Look at line 4. In a lexically scoped language, the variable name 'a' would statically refer to either the outer definition on line 1, or the inner definition on line 6. One or the other. But you can't meaningfully ask "what is the scope of 'a'" in OpenSCAD, because the choice is made at run time, and changes dynamically. So the output is: ECHO: 0,1 Fun question: is any of this behaviour a bug? Doug. On 16 November 2016 at 12:54, Parkinbot <rudolf@parkinbot.com> wrote: > doug.moen wrote > > OpenSCAD2 has a fixed set of data types, based on JSON. What's missing, > > that I've added, is a "record" data type. The current syntax is like > this: > > p = {x=1, y=2}; > > echo(p.x); // ECHO: 1 > > The basic use case is to represent a set of named model parameters. I > also > > intend to use this as the basis for JSON import/export. > > > > Record literals are part of the reason I don't want to use curly braces > > for > > compound actions inside of qualified expressions. The brace characters > are > > reserved for records. > > *p = {x=1, y=2};* is a struct and *p() = {whatever};* a function. A > compiler > and a human can distinquish it. > > To be honest, I still don't know which scope rules apply in OpenSCAD - is't > that a thing that is mainly connected with *{}* despite it gets changed > with > every new release? And there is a lot of confusion going on having two > syntaxes for modules and functions. Why not confess that other languages > have solved this long time ago. Or is your final aim to get rid of modules? > Which would kick out the 95% of the users that don't write their own > functions. > > Also, with OpenSCAD2 I would go so far to allow any module calls in > functions. Why? View them as debugging outputs like echo. But I guess, > again, there will be a scope or a bracket problem. > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19157.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
P
Parkinbot
Thu, Nov 17, 2016 2:07 AM

doug.moen wrote

But you can't meaningfully ask "what is the scope of 'a'" in OpenSCAD,
because the choice is made at run time, and changes dynamically.

Fun question: is any of this behaviour a bug?

Fun answers:
"Wanna start programming with OpenSCAD? Have a pair of dice printed first."
"No, it is not our design that is buggy, is it your expectation."
"We don't want to break freaky code, that has passed our randomizer".

So you are effectively saying, it is more or less random by design, and you
are willing to build even more randomness upon that in OpenSCAD2?

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19185.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > But you can't meaningfully ask "what is the scope of 'a'" in OpenSCAD, > because the choice is made at run time, and changes dynamically. > > Fun question: is any of this behaviour a bug? Fun answers: "Wanna start programming with OpenSCAD? Have a pair of dice printed first." "No, it is not our design that is buggy, is it your expectation." "We don't want to break freaky code, that has passed our randomizer". So you are effectively saying, it is more or less random by design, and you are willing to build even more randomness upon that in OpenSCAD2? -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19185.html Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Thu, Nov 17, 2016 3:38 AM

"So you are effectively saying, it is more or less random by design, and you
are willing to build even more randomness upon that in OpenSCAD2?"

Maybe I was being overly dramatic and critical. But it's increasing clear
that the "backwards compatibility" part of the OpenSCAD2 project is a very
complex undertaking, at least with my current approach of building a new
compiler and VM from scratch.

What I'm building right now is core technology, a compiler and a VM, to be
followed later by a GPU based geometry engine that's integrated with the
VM. The actual language syntax is just a UI on top of the core. To make
faster progress on the core, I need to keep the language part as simple and
regular as possible. Implementing full backward compatibility at this stage
would delay things by a year or so. So my prototype is not compatible with
OpenSCAD, and won't be for some time. I'm hoping that some of my results
will be useful enough that they can be adopted into the OpenSCAD project in
some form, even if I'm not personally building an OpenSCAD compatible
system right now.

In the long term, I don't know what happens.

  1. Maybe the most useful parts of my design get incorporated into
    OpenSCAD, and my project is shelved.
  2. Maybe I release an OpenSCAD-like CAD system with a new and
    incompatible language design. In that case, I won't call it OpenSCAD2 but
    something else. I do not want to create confusion. This will at least free
    me up to fully implement the vision without compromise, with the risk that
    few people will ever use it.
  3. Maybe I do #2, and include the ability to import OpenSCAD scripts, as
    one of the supported file formats. That would entail reimplementing
    OpenSCAD on top of my compiler and VM, with interoperability between the
    two languages. Since OpenSCAD would just be an import format, this
    subproject wouldn't block progress on the main project.
  4. Maybe the OpenSCAD team (Marius, Torsten, et al) will evolve OpenSCAD
    in a direction that makes it more compatible with my compiler and VM,
    introducing minor incompatibilities but cleaning up the language.

One of my concerns about lexical scoping is that I have implemented first
class function values in the standard way, as lexical closures. I don't see
a way to implement first class function values in a way that is both
correct and fully backward compatible with OpenSCAD functions as they
currently work, with weird dynamic scoping. I'd probably end up with an
ugly mess, eg anonymous functions that have different semantics than an
identical named function definition.

On 16 November 2016 at 21:07, Parkinbot rudolf@parkinbot.com wrote:

doug.moen wrote

But you can't meaningfully ask "what is the scope of 'a'" in OpenSCAD,
because the choice is made at run time, and changes dynamically.

Fun question: is any of this behaviour a bug?

Fun answers:
"Wanna start programming with OpenSCAD? Have a pair of dice printed first."
"No, it is not our design that is buggy, is it your expectation."
"We don't want to break freaky code, that has passed our randomizer".

So you are effectively saying, it is more or less random by design, and you
are willing to build even more randomness upon that in OpenSCAD2?

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19185.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

"So you are effectively saying, it is more or less random by design, and you are willing to build even more randomness upon that in OpenSCAD2?" Maybe I was being overly dramatic and critical. But it's increasing clear that the "backwards compatibility" part of the OpenSCAD2 project is a very complex undertaking, at least with my current approach of building a new compiler and VM from scratch. What I'm building right now is core technology, a compiler and a VM, to be followed later by a GPU based geometry engine that's integrated with the VM. The actual language syntax is just a UI on top of the core. To make faster progress on the core, I need to keep the language part as simple and regular as possible. Implementing full backward compatibility at this stage would delay things by a year or so. So my prototype is not compatible with OpenSCAD, and won't be for some time. I'm hoping that some of my results will be useful enough that they can be adopted into the OpenSCAD project in some form, even if I'm not personally building an OpenSCAD compatible system right now. In the long term, I don't know what happens. 1. Maybe the most useful parts of my design get incorporated into OpenSCAD, and my project is shelved. 2. Maybe I release an OpenSCAD-like CAD system with a new and incompatible language design. In that case, I won't call it OpenSCAD2 but something else. I do not want to create confusion. This will at least free me up to fully implement the vision without compromise, with the risk that few people will ever use it. 3. Maybe I do #2, and include the ability to import OpenSCAD scripts, as one of the supported file formats. That would entail reimplementing OpenSCAD on top of my compiler and VM, with interoperability between the two languages. Since OpenSCAD would just be an import format, this subproject wouldn't block progress on the main project. 4. Maybe the OpenSCAD team (Marius, Torsten, et al) will evolve OpenSCAD in a direction that makes it more compatible with my compiler and VM, introducing minor incompatibilities but cleaning up the language. One of my concerns about lexical scoping is that I have implemented first class function values in the standard way, as lexical closures. I don't see a way to implement first class function values in a way that is both correct and fully backward compatible with OpenSCAD functions as they currently work, with weird dynamic scoping. I'd probably end up with an ugly mess, eg anonymous functions that have different semantics than an identical named function definition. On 16 November 2016 at 21:07, Parkinbot <rudolf@parkinbot.com> wrote: > doug.moen wrote > > But you can't meaningfully ask "what is the scope of 'a'" in OpenSCAD, > > because the choice is made at run time, and changes dynamically. > > > > Fun question: is any of this behaviour a bug? > > Fun answers: > "Wanna start programming with OpenSCAD? Have a pair of dice printed first." > "No, it is not our design that is buggy, is it your expectation." > "We don't want to break freaky code, that has passed our randomizer". > > So you are effectively saying, it is more or less random by design, and you > are willing to build even more randomness upon that in OpenSCAD2? > > > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19185.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
M
MichaelAtOz
Fri, Nov 18, 2016 3:21 AM

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19205.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > 1 a = 0; > 2 module m() > 3 { > 4 function f() = a; > 5 x = f(); > 6 a = 1; > 7 y = f(); > 8 echo(x,y); > 9 } > 10 m(); > > So the output is: > ECHO: 0,1 > > Fun question: is any of this behaviour a bug? That makes perfect sense, if you want it the other way you do > a = 0; > module m() > { > a = 1; > function f() = a; > x = f(); > y = f(); > echo(x,y); > } > m(); ----- Admin - PM me if you need anything, or if I've done something stupid... Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19205.html Sent from the OpenSCAD mailing list archive at Nabble.com.
O
otto
Fri, Nov 18, 2016 6:12 AM

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

 function f()=a;  should persistently point to outer value.  The
 fact that function f()=a; created a local variable named with 
 token_id "a" is an artifact.

 In my opinion
 a = 1;
 a = 2;  //should at least produce a warning if not an error.

 Whereas:

 a=1;
 module m()
 {
   a=2;
 }  

  should be legal and provides for a different value of a in the
  two different scopes as it does now.

  a = 1;
  function f() = a;

  Sets the value of "a" as a local variable.  The function then
  always points to the local variable. We should provide a warning if it
  is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19205.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

> doug.moen wrote > > 1 a = 0; > > 2 module m() > > 3 { > > 4 function f() = a; > > 5 x = f(); > > 6 a = 1; > > 7 y = f(); > > 8 echo(x,y); > > 9 } > > 10 m(); > > > > So the output is: > > ECHO: 0,1 > > > > Fun question: is any of this behaviour a bug? I think it is. Heres why. function f() = a; //refers to the outer scope value of a. x = f(); //sets local x to the outer scope value of a. a=1; //This should have no effect on the outer scope. function f()=a; should persistently point to outer value. The fact that function f()=a; created a local variable named with token_id "a" is an artifact. In my opinion a = 1; a = 2; //should at least produce a warning if not an error. Whereas: a=1; module m() { a=2; } should be legal and provides for a different value of a in the two different scopes as it does now. a = 1; function f() = a; Sets the value of "a" as a local variable. The function then always points to the local variable. We should provide a warning if it is redefined. Of course, since this is the behavior and it works, it isn't really a bug, it is an artifact. But it falls into the category of a gotchya, I can think of no case where there isn't a clearer method of writing this code. Everywhere this artifact is used, it tends to obfuscate. Regards Otto > > That makes perfect sense, if you want it the other way you do > > > > a = 0; > > module m() > > { > > a = 1; > > function f() = a; > > x = f(); > > y = f(); > > echo(x,y); > > } > > m(); > > > > > > ----- > Admin - PM me if you need anything, or if I've done something > stupid... > > Unless specifically shown otherwise above, my contribution is in the > Public Domain; to the extent possible under law, I have waived all > copyright and related or neighbouring rights to this work. Obviously > inclusion of works of previous authors is not included in the above. > > The TPP is no simple “trade agreement.” Fight it! > http://www.ourfairdeal.org/ time is running out! -- > View this message in context: > http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19205.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
NH
nop head
Fri, Nov 18, 2016 10:38 AM

If you replace the calls of f() with a then you get the same result and it
makes sense since the first a refers to the outer scope and the second one
to the inner scope. So the function behaves more like a macro text
substitution. But if you move the definition of f outside the module it
always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope was
supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a warning if

it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-

in-expressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

If you replace the calls of f() with a then you get the same result and it makes sense since the first a refers to the outer scope and the second one to the inner scope. So the function behaves more like a macro text substitution. But if you move the definition of f outside the module it always accesses the outer a. So yes it is a strange mixture of lexical and dynamic. I thought scope was supposed to be lexical apart from the $ variables? On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: > > > > > doug.moen wrote > > > 1 a = 0; > > > 2 module m() > > > 3 { > > > 4 function f() = a; > > > 5 x = f(); > > > 6 a = 1; > > > 7 y = f(); > > > 8 echo(x,y); > > > 9 } > > > 10 m(); > > > > > > So the output is: > > > ECHO: 0,1 > > > > > > Fun question: is any of this behaviour a bug? > > I think it is. Heres why. > function f() = a; //refers to the outer scope value of a. > x = f(); //sets local x to the outer scope value of a. > a=1; //This should have no effect on the outer scope. > > function f()=a; should persistently point to outer value. The > fact that function f()=a; created a local variable named with > token_id "a" is an artifact. > > In my opinion > a = 1; > a = 2; //should at least produce a warning if not an error. > > Whereas: > > a=1; > module m() > { > a=2; > } > > should be legal and provides for a different value of a in the > two different scopes as it does now. > > a = 1; > function f() = a; > > Sets the value of "a" as a local variable. The function then > always points to the local variable. We should provide a warning if > it > is redefined. > > Of course, since this is the behavior and it works, it isn't really a > bug, it is an artifact. But it falls into the category of a gotchya, > I can think of no case where there isn't a clearer method of writing > this code. Everywhere this artifact is used, it tends to obfuscate. > > Regards > Otto > > > > > That makes perfect sense, if you want it the other way you do > > > > > > > a = 0; > > > module m() > > > { > > > a = 1; > > > function f() = a; > > > x = f(); > > > y = f(); > > > echo(x,y); > > > } > > > m(); > > > > > > > > > > > > ----- > > Admin - PM me if you need anything, or if I've done something > > stupid... > > > > Unless specifically shown otherwise above, my contribution is in the > > Public Domain; to the extent possible under law, I have waived all > > copyright and related or neighbouring rights to this work. Obviously > > inclusion of works of previous authors is not included in the above. > > > > The TPP is no simple “trade agreement.” Fight it! > > http://www.ourfairdeal.org/ time is running out! -- > > View this message in context: > > http://forum.openscad.org/feedback-let-echo-and-assert- > in-expressions-tp19111p19205.html > > Sent from the OpenSCAD mailing list archive at Nabble.com. > > > > _______________________________________________ > > OpenSCAD mailing list > > 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 >
DM
doug moen
Fri, Nov 18, 2016 1:51 PM

nop head said: I thought scope was supposed to be lexical apart from the $
variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that generates
efficient code, then you'd have to know what the lexical scoping rules
actually are, and implement those rules. It has been frustrating for me to
come up with a clear statement of what the scoping rules are, so that I
could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules, because I
want to work on my VM and geometry engine. Instead, I just implemented the
simplest lexical scoping rule that I could, which is that at the top level
of a script, there is only 1 namespace, and the scope of every variable and
function definition is the entire file (recursive scoping). It's simple and
consistent: it allows recursive definitions, and all you need to know as a
user is that the order of definitions doesn't matter. Plus, it is well
known how to implement this. If I consistently used "sequential scoping"
for everything, then recursive function definitions would be impossible.
The actual scoping rules for OpenSCAD are apparently very complicated, and
I don't know how to implement them using conventional compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it actually
is lexically scoped, except for $ variables. And I'd like to see the
OpenSCAD team document the lexical scoping rules. In particular, what is
the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing first
class function values. An anonymous function literal "captures" the values
of nonlocal lexically scoped variables from surrounding scopes, at the time
the function literal is evaluated. This results in a data structure called
a closure. When the function value is subsequently called, it uses the
captured values. Function definitions work exactly the same way: nonlocal
variables are captured when the function definition is evaluated. The
variables that are captured are the ones visible at the point where the
function is defined, not at the point where the function is called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result and it
makes sense since the first a refers to the outer scope and the second one
to the inner scope. So the function behaves more like a macro text
substitution. But if you move the definition of f outside the module it
always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope was
supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a warning if

it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-

expressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

nop head said: I thought scope was supposed to be lexical apart from the $ variables? That's what I thought too, for years. I think it's *intended* to be lexically scoped, but the code doesn't actually work that way. If you were to try and write a compiler for OpenSCAD, one that generates efficient code, then you'd have to know what the lexical scoping rules actually are, and implement those rules. It has been frustrating for me to come up with a clear statement of what the scoping rules are, so that I could try to implement them in my compiler. For now, I've given up on reverse engineering the scoping rules, because I want to work on my VM and geometry engine. Instead, I just implemented the simplest lexical scoping rule that I could, which is that at the top level of a script, there is only 1 namespace, and the scope of every variable and function definition is the entire file (recursive scoping). It's simple and consistent: it allows recursive definitions, and all you need to know as a user is that the order of definitions doesn't matter. Plus, it is well known how to implement this. If I consistently used "sequential scoping" for everything, then recursive function definitions would be impossible. The actual scoping rules for OpenSCAD are apparently very complicated, and I don't know how to implement them using conventional compiler technology. I think it would be beneficial if OpenSCAD were changed so that it actually is lexically scoped, except for $ variables. And I'd like to see the OpenSCAD team document the lexical scoping rules. In particular, what is the scope of a variable definition? Then maybe at a later date I could revisit this and try to write a compiler that obeys these rules. Well defined lexical scoping rules are important for implementing first class function values. An anonymous function literal "captures" the values of nonlocal lexically scoped variables from surrounding scopes, at the time the function literal is evaluated. This results in a data structure called a closure. When the function value is subsequently called, it uses the captured values. Function definitions work exactly the same way: nonlocal variables are captured when the function definition is evaluated. The variables that are captured are the ones visible at the point where the function is defined, not at the point where the function is called. On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: > If you replace the calls of f() with a then you get the same result and it > makes sense since the first a refers to the outer scope and the second one > to the inner scope. So the function behaves more like a macro text > substitution. But if you move the definition of f outside the module it > always accesses the outer a. > > So yes it is a strange mixture of lexical and dynamic. I thought scope was > supposed to be lexical apart from the $ variables? > > On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: > >> >> >> >> > doug.moen wrote >> > > 1 a = 0; >> > > 2 module m() >> > > 3 { >> > > 4 function f() = a; >> > > 5 x = f(); >> > > 6 a = 1; >> > > 7 y = f(); >> > > 8 echo(x,y); >> > > 9 } >> > > 10 m(); >> > > >> > > So the output is: >> > > ECHO: 0,1 >> > > >> > > Fun question: is any of this behaviour a bug? >> >> I think it is. Heres why. >> function f() = a; //refers to the outer scope value of a. >> x = f(); //sets local x to the outer scope value of a. >> a=1; //This should have no effect on the outer scope. >> >> function f()=a; should persistently point to outer value. The >> fact that function f()=a; created a local variable named with >> token_id "a" is an artifact. >> >> In my opinion >> a = 1; >> a = 2; //should at least produce a warning if not an error. >> >> Whereas: >> >> a=1; >> module m() >> { >> a=2; >> } >> >> should be legal and provides for a different value of a in the >> two different scopes as it does now. >> >> a = 1; >> function f() = a; >> >> Sets the value of "a" as a local variable. The function then >> always points to the local variable. We should provide a warning if >> it >> is redefined. >> >> Of course, since this is the behavior and it works, it isn't really a >> bug, it is an artifact. But it falls into the category of a gotchya, >> I can think of no case where there isn't a clearer method of writing >> this code. Everywhere this artifact is used, it tends to obfuscate. >> >> Regards >> Otto >> >> > >> > That makes perfect sense, if you want it the other way you do >> > >> > >> > > a = 0; >> > > module m() >> > > { >> > > a = 1; >> > > function f() = a; >> > > x = f(); >> > > y = f(); >> > > echo(x,y); >> > > } >> > > m(); >> > >> > >> > >> > >> > >> > ----- >> > Admin - PM me if you need anything, or if I've done something >> > stupid... >> > >> > Unless specifically shown otherwise above, my contribution is in the >> > Public Domain; to the extent possible under law, I have waived all >> > copyright and related or neighbouring rights to this work. Obviously >> > inclusion of works of previous authors is not included in the above. >> > >> > The TPP is no simple “trade agreement.” Fight it! >> > http://www.ourfairdeal.org/ time is running out! -- >> > View this message in context: >> > http://forum.openscad.org/feedback-let-echo-and-assert-in- >> expressions-tp19111p19205.html >> > Sent from the OpenSCAD mailing list archive at Nabble.com. >> > >> > _______________________________________________ >> > OpenSCAD mailing list >> > 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 >> > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
NH
nop head
Fri, Nov 18, 2016 2:03 PM

So is it just a bug in the implementation of nested functions (and
presumably nested modules) or are there other exceptions to lexical scope?

I would be surprised if much or any code relies on this so it could be bug
fixed.

On 18 November 2016 at 13:51, doug moen doug@moens.org wrote:

nop head said: I thought scope was supposed to be lexical apart from the $
variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that generates
efficient code, then you'd have to know what the lexical scoping rules
actually are, and implement those rules. It has been frustrating for me to
come up with a clear statement of what the scoping rules are, so that I
could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules, because I
want to work on my VM and geometry engine. Instead, I just implemented the
simplest lexical scoping rule that I could, which is that at the top level
of a script, there is only 1 namespace, and the scope of every variable and
function definition is the entire file (recursive scoping). It's simple and
consistent: it allows recursive definitions, and all you need to know as a
user is that the order of definitions doesn't matter. Plus, it is well
known how to implement this. If I consistently used "sequential scoping"
for everything, then recursive function definitions would be impossible.
The actual scoping rules for OpenSCAD are apparently very complicated, and
I don't know how to implement them using conventional compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it
actually is lexically scoped, except for $ variables. And I'd like to see
the OpenSCAD team document the lexical scoping rules. In particular, what
is the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing first
class function values. An anonymous function literal "captures" the values
of nonlocal lexically scoped variables from surrounding scopes, at the time
the function literal is evaluated. This results in a data structure called
a closure. When the function value is subsequently called, it uses the
captured values. Function definitions work exactly the same way: nonlocal
variables are captured when the function definition is evaluated. The
variables that are captured are the ones visible at the point where the
function is defined, not at the point where the function is called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result and
it makes sense since the first a refers to the outer scope and the second
one to the inner scope. So the function behaves more like a macro text
substitution. But if you move the definition of f outside the module it
always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope
was supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a warning

if it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-ex

pressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

So is it just a bug in the implementation of nested functions (and presumably nested modules) or are there other exceptions to lexical scope? I would be surprised if much or any code relies on this so it could be bug fixed. On 18 November 2016 at 13:51, doug moen <doug@moens.org> wrote: > nop head said: I thought scope was supposed to be lexical apart from the $ > variables? > > That's what I thought too, for years. I think it's *intended* to be > lexically scoped, but the code doesn't actually work that way. > > If you were to try and write a compiler for OpenSCAD, one that generates > efficient code, then you'd have to know what the lexical scoping rules > actually are, and implement those rules. It has been frustrating for me to > come up with a clear statement of what the scoping rules are, so that I > could try to implement them in my compiler. > > For now, I've given up on reverse engineering the scoping rules, because I > want to work on my VM and geometry engine. Instead, I just implemented the > simplest lexical scoping rule that I could, which is that at the top level > of a script, there is only 1 namespace, and the scope of every variable and > function definition is the entire file (recursive scoping). It's simple and > consistent: it allows recursive definitions, and all you need to know as a > user is that the order of definitions doesn't matter. Plus, it is well > known how to implement this. If I consistently used "sequential scoping" > for everything, then recursive function definitions would be impossible. > The actual scoping rules for OpenSCAD are apparently very complicated, and > I don't know how to implement them using conventional compiler technology. > > I think it would be beneficial if OpenSCAD were changed so that it > actually is lexically scoped, except for $ variables. And I'd like to see > the OpenSCAD team document the lexical scoping rules. In particular, what > is the scope of a variable definition? Then maybe at a later date I could > revisit this and try to write a compiler that obeys these rules. > > Well defined lexical scoping rules are important for implementing first > class function values. An anonymous function literal "captures" the values > of nonlocal lexically scoped variables from surrounding scopes, at the time > the function literal is evaluated. This results in a data structure called > a closure. When the function value is subsequently called, it uses the > captured values. Function definitions work exactly the same way: nonlocal > variables are captured when the function definition is evaluated. The > variables that are captured are the ones visible at the point where the > function is defined, not at the point where the function is called. > > On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: > >> If you replace the calls of f() with a then you get the same result and >> it makes sense since the first a refers to the outer scope and the second >> one to the inner scope. So the function behaves more like a macro text >> substitution. But if you move the definition of f outside the module it >> always accesses the outer a. >> >> So yes it is a strange mixture of lexical and dynamic. I thought scope >> was supposed to be lexical apart from the $ variables? >> >> On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: >> >>> >>> >>> >>> > doug.moen wrote >>> > > 1 a = 0; >>> > > 2 module m() >>> > > 3 { >>> > > 4 function f() = a; >>> > > 5 x = f(); >>> > > 6 a = 1; >>> > > 7 y = f(); >>> > > 8 echo(x,y); >>> > > 9 } >>> > > 10 m(); >>> > > >>> > > So the output is: >>> > > ECHO: 0,1 >>> > > >>> > > Fun question: is any of this behaviour a bug? >>> >>> I think it is. Heres why. >>> function f() = a; //refers to the outer scope value of a. >>> x = f(); //sets local x to the outer scope value of a. >>> a=1; //This should have no effect on the outer scope. >>> >>> function f()=a; should persistently point to outer value. The >>> fact that function f()=a; created a local variable named with >>> token_id "a" is an artifact. >>> >>> In my opinion >>> a = 1; >>> a = 2; //should at least produce a warning if not an error. >>> >>> Whereas: >>> >>> a=1; >>> module m() >>> { >>> a=2; >>> } >>> >>> should be legal and provides for a different value of a in the >>> two different scopes as it does now. >>> >>> a = 1; >>> function f() = a; >>> >>> Sets the value of "a" as a local variable. The function then >>> always points to the local variable. We should provide a warning >>> if it >>> is redefined. >>> >>> Of course, since this is the behavior and it works, it isn't really a >>> bug, it is an artifact. But it falls into the category of a gotchya, >>> I can think of no case where there isn't a clearer method of writing >>> this code. Everywhere this artifact is used, it tends to obfuscate. >>> >>> Regards >>> Otto >>> >>> > >>> > That makes perfect sense, if you want it the other way you do >>> > >>> > >>> > > a = 0; >>> > > module m() >>> > > { >>> > > a = 1; >>> > > function f() = a; >>> > > x = f(); >>> > > y = f(); >>> > > echo(x,y); >>> > > } >>> > > m(); >>> > >>> > >>> > >>> > >>> > >>> > ----- >>> > Admin - PM me if you need anything, or if I've done something >>> > stupid... >>> > >>> > Unless specifically shown otherwise above, my contribution is in the >>> > Public Domain; to the extent possible under law, I have waived all >>> > copyright and related or neighbouring rights to this work. Obviously >>> > inclusion of works of previous authors is not included in the above. >>> > >>> > The TPP is no simple “trade agreement.” Fight it! >>> > http://www.ourfairdeal.org/ time is running out! -- >>> > View this message in context: >>> > http://forum.openscad.org/feedback-let-echo-and-assert-in-ex >>> pressions-tp19111p19205.html >>> > Sent from the OpenSCAD mailing list archive at Nabble.com. >>> > >>> > _______________________________________________ >>> > OpenSCAD mailing list >>> > 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 >>> >> >> >> _______________________________________________ >> OpenSCAD mailing list >> 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 > >
NH
nop head
Fri, Nov 18, 2016 2:11 PM

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That would make compilation difficult! Although I have to say interpreted
languages are always more powerful but slower and while the geometry
evaluation dominates there isn't much advantage to compiling.

On 18 November 2016 at 14:03, nop head nop.head@gmail.com wrote:

So is it just a bug in the implementation of nested functions (and
presumably nested modules) or are there other exceptions to lexical scope?

I would be surprised if much or any code relies on this so it could be bug
fixed.

On 18 November 2016 at 13:51, doug moen doug@moens.org wrote:

nop head said: I thought scope was supposed to be lexical apart from the
$ variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that generates
efficient code, then you'd have to know what the lexical scoping rules
actually are, and implement those rules. It has been frustrating for me to
come up with a clear statement of what the scoping rules are, so that I
could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules, because
I want to work on my VM and geometry engine. Instead, I just implemented
the simplest lexical scoping rule that I could, which is that at the top
level of a script, there is only 1 namespace, and the scope of every
variable and function definition is the entire file (recursive scoping).
It's simple and consistent: it allows recursive definitions, and all you
need to know as a user is that the order of definitions doesn't matter.
Plus, it is well known how to implement this. If I consistently used
"sequential scoping" for everything, then recursive function definitions
would be impossible. The actual scoping rules for OpenSCAD are apparently
very complicated, and I don't know how to implement them using conventional
compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it
actually is lexically scoped, except for $ variables. And I'd like to see
the OpenSCAD team document the lexical scoping rules. In particular, what
is the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing first
class function values. An anonymous function literal "captures" the values
of nonlocal lexically scoped variables from surrounding scopes, at the time
the function literal is evaluated. This results in a data structure called
a closure. When the function value is subsequently called, it uses the
captured values. Function definitions work exactly the same way: nonlocal
variables are captured when the function definition is evaluated. The
variables that are captured are the ones visible at the point where the
function is defined, not at the point where the function is called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result and
it makes sense since the first a refers to the outer scope and the second
one to the inner scope. So the function behaves more like a macro text
substitution. But if you move the definition of f outside the module it
always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope
was supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a warning

if it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-ex

pressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

I just remembered the truly bizarre rule where putting a variable assignment in a module call that is not named in the module definition can override the same name in another module. E.g. b = 2; module x(a) echo(a,b); x(1); x(1, b = 3); ECHO: 1, 2 ECHO: 1, 3 That would make compilation difficult! Although I have to say interpreted languages are always more powerful but slower and while the geometry evaluation dominates there isn't much advantage to compiling. On 18 November 2016 at 14:03, nop head <nop.head@gmail.com> wrote: > So is it just a bug in the implementation of nested functions (and > presumably nested modules) or are there other exceptions to lexical scope? > > I would be surprised if much or any code relies on this so it could be bug > fixed. > > On 18 November 2016 at 13:51, doug moen <doug@moens.org> wrote: > >> nop head said: I thought scope was supposed to be lexical apart from the >> $ variables? >> >> That's what I thought too, for years. I think it's *intended* to be >> lexically scoped, but the code doesn't actually work that way. >> >> If you were to try and write a compiler for OpenSCAD, one that generates >> efficient code, then you'd have to know what the lexical scoping rules >> actually are, and implement those rules. It has been frustrating for me to >> come up with a clear statement of what the scoping rules are, so that I >> could try to implement them in my compiler. >> >> For now, I've given up on reverse engineering the scoping rules, because >> I want to work on my VM and geometry engine. Instead, I just implemented >> the simplest lexical scoping rule that I could, which is that at the top >> level of a script, there is only 1 namespace, and the scope of every >> variable and function definition is the entire file (recursive scoping). >> It's simple and consistent: it allows recursive definitions, and all you >> need to know as a user is that the order of definitions doesn't matter. >> Plus, it is well known how to implement this. If I consistently used >> "sequential scoping" for everything, then recursive function definitions >> would be impossible. The actual scoping rules for OpenSCAD are apparently >> very complicated, and I don't know how to implement them using conventional >> compiler technology. >> >> I think it would be beneficial if OpenSCAD were changed so that it >> actually is lexically scoped, except for $ variables. And I'd like to see >> the OpenSCAD team document the lexical scoping rules. In particular, what >> is the scope of a variable definition? Then maybe at a later date I could >> revisit this and try to write a compiler that obeys these rules. >> >> Well defined lexical scoping rules are important for implementing first >> class function values. An anonymous function literal "captures" the values >> of nonlocal lexically scoped variables from surrounding scopes, at the time >> the function literal is evaluated. This results in a data structure called >> a closure. When the function value is subsequently called, it uses the >> captured values. Function definitions work exactly the same way: nonlocal >> variables are captured when the function definition is evaluated. The >> variables that are captured are the ones visible at the point where the >> function is defined, not at the point where the function is called. >> >> On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: >> >>> If you replace the calls of f() with a then you get the same result and >>> it makes sense since the first a refers to the outer scope and the second >>> one to the inner scope. So the function behaves more like a macro text >>> substitution. But if you move the definition of f outside the module it >>> always accesses the outer a. >>> >>> So yes it is a strange mixture of lexical and dynamic. I thought scope >>> was supposed to be lexical apart from the $ variables? >>> >>> On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: >>> >>>> >>>> >>>> >>>> > doug.moen wrote >>>> > > 1 a = 0; >>>> > > 2 module m() >>>> > > 3 { >>>> > > 4 function f() = a; >>>> > > 5 x = f(); >>>> > > 6 a = 1; >>>> > > 7 y = f(); >>>> > > 8 echo(x,y); >>>> > > 9 } >>>> > > 10 m(); >>>> > > >>>> > > So the output is: >>>> > > ECHO: 0,1 >>>> > > >>>> > > Fun question: is any of this behaviour a bug? >>>> >>>> I think it is. Heres why. >>>> function f() = a; //refers to the outer scope value of a. >>>> x = f(); //sets local x to the outer scope value of a. >>>> a=1; //This should have no effect on the outer scope. >>>> >>>> function f()=a; should persistently point to outer value. The >>>> fact that function f()=a; created a local variable named with >>>> token_id "a" is an artifact. >>>> >>>> In my opinion >>>> a = 1; >>>> a = 2; //should at least produce a warning if not an error. >>>> >>>> Whereas: >>>> >>>> a=1; >>>> module m() >>>> { >>>> a=2; >>>> } >>>> >>>> should be legal and provides for a different value of a in the >>>> two different scopes as it does now. >>>> >>>> a = 1; >>>> function f() = a; >>>> >>>> Sets the value of "a" as a local variable. The function then >>>> always points to the local variable. We should provide a warning >>>> if it >>>> is redefined. >>>> >>>> Of course, since this is the behavior and it works, it isn't really a >>>> bug, it is an artifact. But it falls into the category of a gotchya, >>>> I can think of no case where there isn't a clearer method of writing >>>> this code. Everywhere this artifact is used, it tends to obfuscate. >>>> >>>> Regards >>>> Otto >>>> >>>> > >>>> > That makes perfect sense, if you want it the other way you do >>>> > >>>> > >>>> > > a = 0; >>>> > > module m() >>>> > > { >>>> > > a = 1; >>>> > > function f() = a; >>>> > > x = f(); >>>> > > y = f(); >>>> > > echo(x,y); >>>> > > } >>>> > > m(); >>>> > >>>> > >>>> > >>>> > >>>> > >>>> > ----- >>>> > Admin - PM me if you need anything, or if I've done something >>>> > stupid... >>>> > >>>> > Unless specifically shown otherwise above, my contribution is in the >>>> > Public Domain; to the extent possible under law, I have waived all >>>> > copyright and related or neighbouring rights to this work. Obviously >>>> > inclusion of works of previous authors is not included in the above. >>>> > >>>> > The TPP is no simple “trade agreement.” Fight it! >>>> > http://www.ourfairdeal.org/ time is running out! -- >>>> > View this message in context: >>>> > http://forum.openscad.org/feedback-let-echo-and-assert-in-ex >>>> pressions-tp19111p19205.html >>>> > Sent from the OpenSCAD mailing list archive at Nabble.com. >>>> > >>>> > _______________________________________________ >>>> > OpenSCAD mailing list >>>> > 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 >>>> >>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> 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 >> >> >
DM
doug moen
Fri, Nov 18, 2016 3:15 PM

nophead said: "Although I have to say interpreted languages are always more
powerful but slower and while the geometry evaluation dominates there isn't
much advantage to compiling."

Interpreted languages can be more powerful, but it depends on the
language. OpenSCAD is not a powerful language. Javascript, which is
lexically scoped and compiled, is far more powerful, and the lack of
function values in OpenSCAD is a problem for me.

Suppose we were to extend OpenSCAD so that you can define new geometric
primitives directly in the language. I mean that user defined OpenSCAD
functions would be executed during preview and rendering. And suppose we
make that fast by compiling OpenSCAD code into parallelized GPU code. Then
we would need lexical scoping and a compiler. The functional/declarative
nature of OpenSCAD really helps with this, but the dynamic scoping gets in
the way. Anyway, I think this is worth trying, you could do some really
cool things with this kind of system.

On 18 November 2016 at 09:11, nop head nop.head@gmail.com wrote:

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That would make compilation difficult! Although I have to say interpreted
languages are always more powerful but slower and while the geometry
evaluation dominates there isn't much advantage to compiling.

On 18 November 2016 at 14:03, nop head nop.head@gmail.com wrote:

So is it just a bug in the implementation of nested functions (and
presumably nested modules) or are there other exceptions to lexical scope?

I would be surprised if much or any code relies on this so it could be
bug fixed.

On 18 November 2016 at 13:51, doug moen doug@moens.org wrote:

nop head said: I thought scope was supposed to be lexical apart from the
$ variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that generates
efficient code, then you'd have to know what the lexical scoping rules
actually are, and implement those rules. It has been frustrating for me to
come up with a clear statement of what the scoping rules are, so that I
could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules, because
I want to work on my VM and geometry engine. Instead, I just implemented
the simplest lexical scoping rule that I could, which is that at the top
level of a script, there is only 1 namespace, and the scope of every
variable and function definition is the entire file (recursive scoping).
It's simple and consistent: it allows recursive definitions, and all you
need to know as a user is that the order of definitions doesn't matter.
Plus, it is well known how to implement this. If I consistently used
"sequential scoping" for everything, then recursive function definitions
would be impossible. The actual scoping rules for OpenSCAD are apparently
very complicated, and I don't know how to implement them using conventional
compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it
actually is lexically scoped, except for $ variables. And I'd like to see
the OpenSCAD team document the lexical scoping rules. In particular, what
is the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing first
class function values. An anonymous function literal "captures" the values
of nonlocal lexically scoped variables from surrounding scopes, at the time
the function literal is evaluated. This results in a data structure called
a closure. When the function value is subsequently called, it uses the
captured values. Function definitions work exactly the same way: nonlocal
variables are captured when the function definition is evaluated. The
variables that are captured are the ones visible at the point where the
function is defined, not at the point where the function is called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result and
it makes sense since the first a refers to the outer scope and the second
one to the inner scope. So the function behaves more like a macro text
substitution. But if you move the definition of f outside the module it
always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope
was supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a warning

if it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-ex

pressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

nophead said: "Although I have to say interpreted languages are always more powerful but slower and while the geometry evaluation dominates there isn't much advantage to compiling." Interpreted languages *can* be more powerful, but it depends on the language. OpenSCAD is not a powerful language. Javascript, which is lexically scoped and compiled, is far more powerful, and the lack of function values in OpenSCAD is a problem for me. Suppose we were to extend OpenSCAD so that you can define new geometric primitives directly in the language. I mean that user defined OpenSCAD functions would be executed during preview and rendering. And suppose we make that fast by compiling OpenSCAD code into parallelized GPU code. Then we would need lexical scoping and a compiler. The functional/declarative nature of OpenSCAD really helps with this, but the dynamic scoping gets in the way. Anyway, I think this is worth trying, you could do some really cool things with this kind of system. On 18 November 2016 at 09:11, nop head <nop.head@gmail.com> wrote: > I just remembered the truly bizarre rule where putting a variable > assignment in a module call that is not named in the module definition can > override the same name in another module. E.g. > > b = 2; > module x(a) echo(a,b); > > x(1); > x(1, b = 3); > > ECHO: 1, 2 > > ECHO: 1, 3 > > > > That would make compilation difficult! Although I have to say interpreted > languages are always more powerful but slower and while the geometry > evaluation dominates there isn't much advantage to compiling. > > > > On 18 November 2016 at 14:03, nop head <nop.head@gmail.com> wrote: > >> So is it just a bug in the implementation of nested functions (and >> presumably nested modules) or are there other exceptions to lexical scope? >> >> I would be surprised if much or any code relies on this so it could be >> bug fixed. >> >> On 18 November 2016 at 13:51, doug moen <doug@moens.org> wrote: >> >>> nop head said: I thought scope was supposed to be lexical apart from the >>> $ variables? >>> >>> That's what I thought too, for years. I think it's *intended* to be >>> lexically scoped, but the code doesn't actually work that way. >>> >>> If you were to try and write a compiler for OpenSCAD, one that generates >>> efficient code, then you'd have to know what the lexical scoping rules >>> actually are, and implement those rules. It has been frustrating for me to >>> come up with a clear statement of what the scoping rules are, so that I >>> could try to implement them in my compiler. >>> >>> For now, I've given up on reverse engineering the scoping rules, because >>> I want to work on my VM and geometry engine. Instead, I just implemented >>> the simplest lexical scoping rule that I could, which is that at the top >>> level of a script, there is only 1 namespace, and the scope of every >>> variable and function definition is the entire file (recursive scoping). >>> It's simple and consistent: it allows recursive definitions, and all you >>> need to know as a user is that the order of definitions doesn't matter. >>> Plus, it is well known how to implement this. If I consistently used >>> "sequential scoping" for everything, then recursive function definitions >>> would be impossible. The actual scoping rules for OpenSCAD are apparently >>> very complicated, and I don't know how to implement them using conventional >>> compiler technology. >>> >>> I think it would be beneficial if OpenSCAD were changed so that it >>> actually is lexically scoped, except for $ variables. And I'd like to see >>> the OpenSCAD team document the lexical scoping rules. In particular, what >>> is the scope of a variable definition? Then maybe at a later date I could >>> revisit this and try to write a compiler that obeys these rules. >>> >>> Well defined lexical scoping rules are important for implementing first >>> class function values. An anonymous function literal "captures" the values >>> of nonlocal lexically scoped variables from surrounding scopes, at the time >>> the function literal is evaluated. This results in a data structure called >>> a closure. When the function value is subsequently called, it uses the >>> captured values. Function definitions work exactly the same way: nonlocal >>> variables are captured when the function definition is evaluated. The >>> variables that are captured are the ones visible at the point where the >>> function is defined, not at the point where the function is called. >>> >>> On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: >>> >>>> If you replace the calls of f() with a then you get the same result and >>>> it makes sense since the first a refers to the outer scope and the second >>>> one to the inner scope. So the function behaves more like a macro text >>>> substitution. But if you move the definition of f outside the module it >>>> always accesses the outer a. >>>> >>>> So yes it is a strange mixture of lexical and dynamic. I thought scope >>>> was supposed to be lexical apart from the $ variables? >>>> >>>> On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: >>>> >>>>> >>>>> >>>>> >>>>> > doug.moen wrote >>>>> > > 1 a = 0; >>>>> > > 2 module m() >>>>> > > 3 { >>>>> > > 4 function f() = a; >>>>> > > 5 x = f(); >>>>> > > 6 a = 1; >>>>> > > 7 y = f(); >>>>> > > 8 echo(x,y); >>>>> > > 9 } >>>>> > > 10 m(); >>>>> > > >>>>> > > So the output is: >>>>> > > ECHO: 0,1 >>>>> > > >>>>> > > Fun question: is any of this behaviour a bug? >>>>> >>>>> I think it is. Heres why. >>>>> function f() = a; //refers to the outer scope value of a. >>>>> x = f(); //sets local x to the outer scope value of a. >>>>> a=1; //This should have no effect on the outer scope. >>>>> >>>>> function f()=a; should persistently point to outer value. The >>>>> fact that function f()=a; created a local variable named with >>>>> token_id "a" is an artifact. >>>>> >>>>> In my opinion >>>>> a = 1; >>>>> a = 2; //should at least produce a warning if not an error. >>>>> >>>>> Whereas: >>>>> >>>>> a=1; >>>>> module m() >>>>> { >>>>> a=2; >>>>> } >>>>> >>>>> should be legal and provides for a different value of a in the >>>>> two different scopes as it does now. >>>>> >>>>> a = 1; >>>>> function f() = a; >>>>> >>>>> Sets the value of "a" as a local variable. The function then >>>>> always points to the local variable. We should provide a warning >>>>> if it >>>>> is redefined. >>>>> >>>>> Of course, since this is the behavior and it works, it isn't really a >>>>> bug, it is an artifact. But it falls into the category of a gotchya, >>>>> I can think of no case where there isn't a clearer method of writing >>>>> this code. Everywhere this artifact is used, it tends to obfuscate. >>>>> >>>>> Regards >>>>> Otto >>>>> >>>>> > >>>>> > That makes perfect sense, if you want it the other way you do >>>>> > >>>>> > >>>>> > > a = 0; >>>>> > > module m() >>>>> > > { >>>>> > > a = 1; >>>>> > > function f() = a; >>>>> > > x = f(); >>>>> > > y = f(); >>>>> > > echo(x,y); >>>>> > > } >>>>> > > m(); >>>>> > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> > ----- >>>>> > Admin - PM me if you need anything, or if I've done something >>>>> > stupid... >>>>> > >>>>> > Unless specifically shown otherwise above, my contribution is in the >>>>> > Public Domain; to the extent possible under law, I have waived all >>>>> > copyright and related or neighbouring rights to this work. Obviously >>>>> > inclusion of works of previous authors is not included in the above. >>>>> > >>>>> > The TPP is no simple “trade agreement.” Fight it! >>>>> > http://www.ourfairdeal.org/ time is running out! -- >>>>> > View this message in context: >>>>> > http://forum.openscad.org/feedback-let-echo-and-assert-in-ex >>>>> pressions-tp19111p19205.html >>>>> > Sent from the OpenSCAD mailing list archive at Nabble.com. >>>>> > >>>>> > _______________________________________________ >>>>> > OpenSCAD mailing list >>>>> > Discuss@lists.openscad.org >>>>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.ope >>>>> nscad.org >>>>> >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> 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 >>>> >>>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> 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 > >
A
adrian
Fri, Nov 18, 2016 3:16 PM

nophead wrote

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

I thought that was just an artifact of the $ variables that can be passed
in.  Basically, you can override any external variable by specifying a
particular value in the function arguments, making a scope bubble layer that
goes between the local and outer scope.

Thought it was odd, but interesting.

A

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19213.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

nophead wrote > I just remembered the truly bizarre rule where putting a variable > assignment in a module call that is not named in the module definition can > override the same name in another module. E.g. > > b = 2; > module x(a) echo(a,b); > > x(1); > x(1, b = 3); > > ECHO: 1, 2 > > ECHO: 1, 3 I thought that was just an artifact of the $ variables that can be passed in. Basically, you can override any external variable by specifying a particular value in the function arguments, making a scope bubble layer that goes between the local and outer scope. Thought it was odd, but interesting. A -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19213.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Fri, Nov 18, 2016 3:28 PM

On Nov 18, 2016, at 09:11, nop head nop.head@gmail.com wrote:

module x(a) echo(a,b);
x(1, b = 3);

We merge the entire argument list into the local scope of the module at call time. This was probably initially done to pass dynamically scoped variables. I would consider the fact that regular assignments slipped through a bug.

-Marius

> On Nov 18, 2016, at 09:11, nop head <nop.head@gmail.com> wrote: > > module x(a) echo(a,b); > x(1, b = 3); > We merge the entire argument list into the local scope of the module at call time. This was probably initially done to pass dynamically scoped variables. I would consider the fact that regular assignments slipped through a bug. -Marius
MK
Marius Kintel
Fri, Nov 18, 2016 3:39 PM

On Nov 18, 2016, at 08:51, doug moen doug@moens.org wrote:

I think it would be beneficial if OpenSCAD were changed so that it actually is lexically scoped, except for $ variables.

I agree. I’d like to see a way of providing very clear messages to people exploiting this behavior that it’s deprecated, ideally with a way of upgrading code to follow the new rules.

And I'd like to see the OpenSCAD team document the lexical scoping rules. In particular, what is the scope of a variable definition? Then maybe at a later date I could revisit this and try to write a compiler that obeys these rules.

I’m not sure anyone wants to document these rules as they’re mostly artifacts of poorly written/tested code in the past. Extracting docs from code is not always easy..
Most of this is implicitly available as tests. Any new compiler could reuse these test cases.
Rather than documenting it, we could always identify usage of such with tests, and write rules on the AST level to detect usage of said features, and potentially provide an upgrade path.

-Marius

> On Nov 18, 2016, at 08:51, doug moen <doug@moens.org> wrote: > > I think it would be beneficial if OpenSCAD were changed so that it actually is lexically scoped, except for $ variables. I agree. I’d like to see a way of providing very clear messages to people exploiting this behavior that it’s deprecated, ideally with a way of upgrading code to follow the new rules. > And I'd like to see the OpenSCAD team document the lexical scoping rules. In particular, what is the scope of a variable definition? Then maybe at a later date I could revisit this and try to write a compiler that obeys these rules. > I’m not sure anyone wants to document these rules as they’re mostly artifacts of poorly written/tested code in the past. Extracting docs from code is not always easy.. Most of this is implicitly available as tests. Any new compiler could reuse these test cases. Rather than documenting it, we could always identify usage of such with tests, and write rules on the AST level to detect usage of said features, and potentially provide an upgrade path. -Marius
NH
nop head
Fri, Nov 18, 2016 3:47 PM

On 18 November 2016 at 15:15, doug moen doug@moens.org wrote:

nophead said: "Although I have to say interpreted languages are always
more powerful but slower and while the geometry evaluation dominates there
isn't much advantage to compiling."

Interpreted languages can be more powerful, but it depends on the
language. OpenSCAD is not a powerful language. Javascript, which is
lexically scoped and compiled, is far more powerful, and the lack of
function values in OpenSCAD is a problem for me.

Suppose we were to extend OpenSCAD so that you can define new geometric
primitives directly in the language. I mean that user defined OpenSCAD
functions would be executed during preview and rendering. And suppose we
make that fast by compiling OpenSCAD code into parallelized GPU code. Then
we would need lexical scoping and a compiler. The functional/declarative
nature of OpenSCAD really helps with this, but the dynamic scoping gets in
the way. Anyway, I think this is worth trying, you could do some really
cool things with this kind of system.

Do I understand this right? You are proposing making OpenScad powerful
enough to replace GCAL so things like union can be written at the user
level, and have it run on a GPU?

On 18 November 2016 at 09:11, nop head nop.head@gmail.com wrote:

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That would make compilation difficult! Although I have to say interpreted
languages are always more powerful but slower and while the geometry
evaluation dominates there isn't much advantage to compiling.

On 18 November 2016 at 14:03, nop head nop.head@gmail.com wrote:

So is it just a bug in the implementation of nested functions (and
presumably nested modules) or are there other exceptions to lexical scope?

I would be surprised if much or any code relies on this so it could be
bug fixed.

On 18 November 2016 at 13:51, doug moen doug@moens.org wrote:

nop head said: I thought scope was supposed to be lexical apart from
the $ variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that
generates efficient code, then you'd have to know what the lexical scoping
rules actually are, and implement those rules. It has been frustrating for
me to come up with a clear statement of what the scoping rules are, so that
I could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules,
because I want to work on my VM and geometry engine. Instead, I just
implemented the simplest lexical scoping rule that I could, which is that
at the top level of a script, there is only 1 namespace, and the scope of
every variable and function definition is the entire file (recursive
scoping). It's simple and consistent: it allows recursive definitions, and
all you need to know as a user is that the order of definitions doesn't
matter. Plus, it is well known how to implement this. If I consistently
used "sequential scoping" for everything, then recursive function
definitions would be impossible. The actual scoping rules for OpenSCAD are
apparently very complicated, and I don't know how to implement them using
conventional compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it
actually is lexically scoped, except for $ variables. And I'd like to see
the OpenSCAD team document the lexical scoping rules. In particular, what
is the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing first
class function values. An anonymous function literal "captures" the values
of nonlocal lexically scoped variables from surrounding scopes, at the time
the function literal is evaluated. This results in a data structure called
a closure. When the function value is subsequently called, it uses the
captured values. Function definitions work exactly the same way: nonlocal
variables are captured when the function definition is evaluated. The
variables that are captured are the ones visible at the point where the
function is defined, not at the point where the function is called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result
and it makes sense since the first a refers to the outer scope and the
second one to the inner scope. So the function behaves more like a macro
text substitution. But if you move the definition of f outside the module
it always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought scope
was supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer
scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a

warning if it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-ex

pressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

On 18 November 2016 at 15:15, doug moen <doug@moens.org> wrote: > nophead said: "Although I have to say interpreted languages are always > more powerful but slower and while the geometry evaluation dominates there > isn't much advantage to compiling." > > Interpreted languages *can* be more powerful, but it depends on the > language. OpenSCAD is not a powerful language. Javascript, which is > lexically scoped and compiled, is far more powerful, and the lack of > function values in OpenSCAD is a problem for me. > > Suppose we were to extend OpenSCAD so that you can define new geometric > primitives directly in the language. I mean that user defined OpenSCAD > functions would be executed during preview and rendering. And suppose we > make that fast by compiling OpenSCAD code into parallelized GPU code. Then > we would need lexical scoping and a compiler. The functional/declarative > nature of OpenSCAD really helps with this, but the dynamic scoping gets in > the way. Anyway, I think this is worth trying, you could do some really > cool things with this kind of system. > Do I understand this right? You are proposing making OpenScad powerful enough to replace GCAL so things like union can be written at the user level, and have it run on a GPU? > > On 18 November 2016 at 09:11, nop head <nop.head@gmail.com> wrote: > >> I just remembered the truly bizarre rule where putting a variable >> assignment in a module call that is not named in the module definition can >> override the same name in another module. E.g. >> >> b = 2; >> module x(a) echo(a,b); >> >> x(1); >> x(1, b = 3); >> >> ECHO: 1, 2 >> >> ECHO: 1, 3 >> >> >> >> That would make compilation difficult! Although I have to say interpreted >> languages are always more powerful but slower and while the geometry >> evaluation dominates there isn't much advantage to compiling. >> >> >> >> On 18 November 2016 at 14:03, nop head <nop.head@gmail.com> wrote: >> >>> So is it just a bug in the implementation of nested functions (and >>> presumably nested modules) or are there other exceptions to lexical scope? >>> >>> I would be surprised if much or any code relies on this so it could be >>> bug fixed. >>> >>> On 18 November 2016 at 13:51, doug moen <doug@moens.org> wrote: >>> >>>> nop head said: I thought scope was supposed to be lexical apart from >>>> the $ variables? >>>> >>>> That's what I thought too, for years. I think it's *intended* to be >>>> lexically scoped, but the code doesn't actually work that way. >>>> >>>> If you were to try and write a compiler for OpenSCAD, one that >>>> generates efficient code, then you'd have to know what the lexical scoping >>>> rules actually are, and implement those rules. It has been frustrating for >>>> me to come up with a clear statement of what the scoping rules are, so that >>>> I could try to implement them in my compiler. >>>> >>>> For now, I've given up on reverse engineering the scoping rules, >>>> because I want to work on my VM and geometry engine. Instead, I just >>>> implemented the simplest lexical scoping rule that I could, which is that >>>> at the top level of a script, there is only 1 namespace, and the scope of >>>> every variable and function definition is the entire file (recursive >>>> scoping). It's simple and consistent: it allows recursive definitions, and >>>> all you need to know as a user is that the order of definitions doesn't >>>> matter. Plus, it is well known how to implement this. If I consistently >>>> used "sequential scoping" for everything, then recursive function >>>> definitions would be impossible. The actual scoping rules for OpenSCAD are >>>> apparently very complicated, and I don't know how to implement them using >>>> conventional compiler technology. >>>> >>>> I think it would be beneficial if OpenSCAD were changed so that it >>>> actually is lexically scoped, except for $ variables. And I'd like to see >>>> the OpenSCAD team document the lexical scoping rules. In particular, what >>>> is the scope of a variable definition? Then maybe at a later date I could >>>> revisit this and try to write a compiler that obeys these rules. >>>> >>>> Well defined lexical scoping rules are important for implementing first >>>> class function values. An anonymous function literal "captures" the values >>>> of nonlocal lexically scoped variables from surrounding scopes, at the time >>>> the function literal is evaluated. This results in a data structure called >>>> a closure. When the function value is subsequently called, it uses the >>>> captured values. Function definitions work exactly the same way: nonlocal >>>> variables are captured when the function definition is evaluated. The >>>> variables that are captured are the ones visible at the point where the >>>> function is defined, not at the point where the function is called. >>>> >>>> On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: >>>> >>>>> If you replace the calls of f() with a then you get the same result >>>>> and it makes sense since the first a refers to the outer scope and the >>>>> second one to the inner scope. So the function behaves more like a macro >>>>> text substitution. But if you move the definition of f outside the module >>>>> it always accesses the outer a. >>>>> >>>>> So yes it is a strange mixture of lexical and dynamic. I thought scope >>>>> was supposed to be lexical apart from the $ variables? >>>>> >>>>> On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: >>>>> >>>>>> >>>>>> >>>>>> >>>>>> > doug.moen wrote >>>>>> > > 1 a = 0; >>>>>> > > 2 module m() >>>>>> > > 3 { >>>>>> > > 4 function f() = a; >>>>>> > > 5 x = f(); >>>>>> > > 6 a = 1; >>>>>> > > 7 y = f(); >>>>>> > > 8 echo(x,y); >>>>>> > > 9 } >>>>>> > > 10 m(); >>>>>> > > >>>>>> > > So the output is: >>>>>> > > ECHO: 0,1 >>>>>> > > >>>>>> > > Fun question: is any of this behaviour a bug? >>>>>> >>>>>> I think it is. Heres why. >>>>>> function f() = a; //refers to the outer scope value of a. >>>>>> x = f(); //sets local x to the outer scope value of a. >>>>>> a=1; //This should have no effect on the outer >>>>>> scope. >>>>>> >>>>>> function f()=a; should persistently point to outer value. The >>>>>> fact that function f()=a; created a local variable named with >>>>>> token_id "a" is an artifact. >>>>>> >>>>>> In my opinion >>>>>> a = 1; >>>>>> a = 2; //should at least produce a warning if not an error. >>>>>> >>>>>> Whereas: >>>>>> >>>>>> a=1; >>>>>> module m() >>>>>> { >>>>>> a=2; >>>>>> } >>>>>> >>>>>> should be legal and provides for a different value of a in the >>>>>> two different scopes as it does now. >>>>>> >>>>>> a = 1; >>>>>> function f() = a; >>>>>> >>>>>> Sets the value of "a" as a local variable. The function then >>>>>> always points to the local variable. We should provide a >>>>>> warning if it >>>>>> is redefined. >>>>>> >>>>>> Of course, since this is the behavior and it works, it isn't really a >>>>>> bug, it is an artifact. But it falls into the category of a gotchya, >>>>>> I can think of no case where there isn't a clearer method of writing >>>>>> this code. Everywhere this artifact is used, it tends to obfuscate. >>>>>> >>>>>> Regards >>>>>> Otto >>>>>> >>>>>> > >>>>>> > That makes perfect sense, if you want it the other way you do >>>>>> > >>>>>> > >>>>>> > > a = 0; >>>>>> > > module m() >>>>>> > > { >>>>>> > > a = 1; >>>>>> > > function f() = a; >>>>>> > > x = f(); >>>>>> > > y = f(); >>>>>> > > echo(x,y); >>>>>> > > } >>>>>> > > m(); >>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>>> > ----- >>>>>> > Admin - PM me if you need anything, or if I've done something >>>>>> > stupid... >>>>>> > >>>>>> > Unless specifically shown otherwise above, my contribution is in the >>>>>> > Public Domain; to the extent possible under law, I have waived all >>>>>> > copyright and related or neighbouring rights to this work. Obviously >>>>>> > inclusion of works of previous authors is not included in the above. >>>>>> > >>>>>> > The TPP is no simple “trade agreement.” Fight it! >>>>>> > http://www.ourfairdeal.org/ time is running out! -- >>>>>> > View this message in context: >>>>>> > http://forum.openscad.org/feedback-let-echo-and-assert-in-ex >>>>>> pressions-tp19111p19205.html >>>>>> > Sent from the OpenSCAD mailing list archive at Nabble.com. >>>>>> > >>>>>> > _______________________________________________ >>>>>> > OpenSCAD mailing list >>>>>> > Discuss@lists.openscad.org >>>>>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.ope >>>>>> nscad.org >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> OpenSCAD mailing list >>>>>> 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 >>>>> >>>>> >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> 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 >> >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
DM
doug moen
Fri, Nov 18, 2016 5:11 PM

nophead said: "Do I understand this right? You are proposing making
OpenScad powerful enough to replace GCAL so things like union can be
written at the user level, and have it run on a GPU?"

Yes, that is what I am working towards. I have the implementation worked
out, and hopefully next year I'll have something to demo. Initially, it
won't be OpenSCAD (or OpenSCAD2), it will instead be a simplified
OpenSCAD-like language with lexical scoping and other accommodations for
GPU compilation. And it won't "replace CGAL", since I'm using different
data structures and algorithms, so the behaviour of union, etc will be
different. I'm hoping it will be faster, but I can't make claims until I
have working code.

On 18 November 2016 at 10:47, nop head nop.head@gmail.com wrote:

On 18 November 2016 at 15:15, doug moen doug@moens.org wrote:

nophead said: "Although I have to say interpreted languages are always
more powerful but slower and while the geometry evaluation dominates there
isn't much advantage to compiling."

Interpreted languages can be more powerful, but it depends on the
language. OpenSCAD is not a powerful language. Javascript, which is
lexically scoped and compiled, is far more powerful, and the lack of
function values in OpenSCAD is a problem for me.

Suppose we were to extend OpenSCAD so that you can define new geometric
primitives directly in the language. I mean that user defined OpenSCAD
functions would be executed during preview and rendering. And suppose we
make that fast by compiling OpenSCAD code into parallelized GPU code. Then
we would need lexical scoping and a compiler. The functional/declarative
nature of OpenSCAD really helps with this, but the dynamic scoping gets in
the way. Anyway, I think this is worth trying, you could do some really
cool things with this kind of system.

Do I understand this right? You are proposing making OpenScad powerful
enough to replace GCAL so things like union can be written at the user
level, and have it run on a GPU?

On 18 November 2016 at 09:11, nop head nop.head@gmail.com wrote:

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That would make compilation difficult! Although I have to say
interpreted languages are always more powerful but slower and while the
geometry evaluation dominates there isn't much advantage to compiling.

On 18 November 2016 at 14:03, nop head nop.head@gmail.com wrote:

So is it just a bug in the implementation of nested functions (and
presumably nested modules) or are there other exceptions to lexical scope?

I would be surprised if much or any code relies on this so it could be
bug fixed.

On 18 November 2016 at 13:51, doug moen doug@moens.org wrote:

nop head said: I thought scope was supposed to be lexical apart from
the $ variables?

That's what I thought too, for years. I think it's intended to be
lexically scoped, but the code doesn't actually work that way.

If you were to try and write a compiler for OpenSCAD, one that
generates efficient code, then you'd have to know what the lexical scoping
rules actually are, and implement those rules. It has been frustrating for
me to come up with a clear statement of what the scoping rules are, so that
I could try to implement them in my compiler.

For now, I've given up on reverse engineering the scoping rules,
because I want to work on my VM and geometry engine. Instead, I just
implemented the simplest lexical scoping rule that I could, which is that
at the top level of a script, there is only 1 namespace, and the scope of
every variable and function definition is the entire file (recursive
scoping). It's simple and consistent: it allows recursive definitions, and
all you need to know as a user is that the order of definitions doesn't
matter. Plus, it is well known how to implement this. If I consistently
used "sequential scoping" for everything, then recursive function
definitions would be impossible. The actual scoping rules for OpenSCAD are
apparently very complicated, and I don't know how to implement them using
conventional compiler technology.

I think it would be beneficial if OpenSCAD were changed so that it
actually is lexically scoped, except for $ variables. And I'd like to see
the OpenSCAD team document the lexical scoping rules. In particular, what
is the scope of a variable definition? Then maybe at a later date I could
revisit this and try to write a compiler that obeys these rules.

Well defined lexical scoping rules are important for implementing
first class function values. An anonymous function literal "captures" the
values of nonlocal lexically scoped variables from surrounding scopes, at
the time the function literal is evaluated. This results in a data
structure called a closure. When the function value is subsequently called,
it uses the captured values. Function definitions work exactly the same
way: nonlocal variables are captured when the function definition is
evaluated. The variables that are captured are the ones visible at the
point where the function is defined, not at the point where the function is
called.

On 18 November 2016 at 05:38, nop head nop.head@gmail.com wrote:

If you replace the calls of f() with a then you get the same result
and it makes sense since the first a refers to the outer scope and the
second one to the inner scope. So the function behaves more like a macro
text substitution. But if you move the definition of f outside the module
it always accesses the outer a.

So yes it is a strange mixture of lexical and dynamic. I thought
scope was supposed to be lexical apart from the $ variables?

On 18 November 2016 at 06:12, otto otto@123phase.com wrote:

doug.moen wrote

1    a = 0;
2    module m()
3    {
4        function f() = a;
5        x = f();
6        a = 1;
7        y = f();
8        echo(x,y);
9    }
10  m();

So the output is:
ECHO: 0,1

Fun question: is any of this behaviour a bug?

I think it is.  Heres why.
function f() = a;  //refers to the outer scope value of a.
x = f();          //sets local x to the outer scope value of a.
a=1;              //This should have no effect on the outer
scope.

  function f()=a;  should persistently point to outer value.  The
  fact that function f()=a; created a local variable named with
  token_id "a" is an artifact.

  In my opinion
  a = 1;
  a = 2;  //should at least produce a warning if not an error.

  Whereas:

  a=1;
  module m()
  {
    a=2;
  }

   should be legal and provides for a different value of a in the
   two different scopes as it does now.

   a = 1;
   function f() = a;

   Sets the value of "a" as a local variable.  The function then
   always points to the local variable. We should provide a

warning if it
is redefined.

Of course, since this is the behavior and it works, it isn't really a
bug, it is an artifact.  But it falls into the category of a gotchya,
I can think of no case where there isn't a clearer method of writing
this code.  Everywhere this artifact is used, it tends to obfuscate.

Regards
Otto

That makes perfect sense, if you want it the other way you do

 a = 0;
 module m()
 {
     a = 1;
     function f() = a;
     x = f();
     y = f();
     echo(x,y);
  }
m();

Admin - PM me if you need anything, or if I've done something
stupid...

Unless specifically shown otherwise above, my contribution is in

the

Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work.

Obviously

inclusion of works of previous authors is not included in the

above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out! --
View this message in context:
http://forum.openscad.org/feedback-let-echo-and-assert-in-ex

pressions-tp19111p19205.html

Sent from the OpenSCAD mailing list archive at Nabble.com.


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

nophead said: "Do I understand this right? You are proposing making OpenScad powerful enough to replace GCAL so things like union can be written at the user level, and have it run on a GPU?" Yes, that is what I am working towards. I have the implementation worked out, and hopefully next year I'll have something to demo. Initially, it won't be OpenSCAD (or OpenSCAD2), it will instead be a simplified OpenSCAD-like language with lexical scoping and other accommodations for GPU compilation. And it won't "replace CGAL", since I'm using different data structures and algorithms, so the behaviour of union, etc will be different. I'm hoping it will be faster, but I can't make claims until I have working code. On 18 November 2016 at 10:47, nop head <nop.head@gmail.com> wrote: > > > On 18 November 2016 at 15:15, doug moen <doug@moens.org> wrote: > >> nophead said: "Although I have to say interpreted languages are always >> more powerful but slower and while the geometry evaluation dominates there >> isn't much advantage to compiling." >> >> Interpreted languages *can* be more powerful, but it depends on the >> language. OpenSCAD is not a powerful language. Javascript, which is >> lexically scoped and compiled, is far more powerful, and the lack of >> function values in OpenSCAD is a problem for me. >> >> Suppose we were to extend OpenSCAD so that you can define new geometric >> primitives directly in the language. I mean that user defined OpenSCAD >> functions would be executed during preview and rendering. And suppose we >> make that fast by compiling OpenSCAD code into parallelized GPU code. Then >> we would need lexical scoping and a compiler. The functional/declarative >> nature of OpenSCAD really helps with this, but the dynamic scoping gets in >> the way. Anyway, I think this is worth trying, you could do some really >> cool things with this kind of system. >> > > Do I understand this right? You are proposing making OpenScad powerful > enough to replace GCAL so things like union can be written at the user > level, and have it run on a GPU? > > >> >> On 18 November 2016 at 09:11, nop head <nop.head@gmail.com> wrote: >> >>> I just remembered the truly bizarre rule where putting a variable >>> assignment in a module call that is not named in the module definition can >>> override the same name in another module. E.g. >>> >>> b = 2; >>> module x(a) echo(a,b); >>> >>> x(1); >>> x(1, b = 3); >>> >>> ECHO: 1, 2 >>> >>> ECHO: 1, 3 >>> >>> >>> >>> That would make compilation difficult! Although I have to say >>> interpreted languages are always more powerful but slower and while the >>> geometry evaluation dominates there isn't much advantage to compiling. >>> >>> >>> >>> On 18 November 2016 at 14:03, nop head <nop.head@gmail.com> wrote: >>> >>>> So is it just a bug in the implementation of nested functions (and >>>> presumably nested modules) or are there other exceptions to lexical scope? >>>> >>>> I would be surprised if much or any code relies on this so it could be >>>> bug fixed. >>>> >>>> On 18 November 2016 at 13:51, doug moen <doug@moens.org> wrote: >>>> >>>>> nop head said: I thought scope was supposed to be lexical apart from >>>>> the $ variables? >>>>> >>>>> That's what I thought too, for years. I think it's *intended* to be >>>>> lexically scoped, but the code doesn't actually work that way. >>>>> >>>>> If you were to try and write a compiler for OpenSCAD, one that >>>>> generates efficient code, then you'd have to know what the lexical scoping >>>>> rules actually are, and implement those rules. It has been frustrating for >>>>> me to come up with a clear statement of what the scoping rules are, so that >>>>> I could try to implement them in my compiler. >>>>> >>>>> For now, I've given up on reverse engineering the scoping rules, >>>>> because I want to work on my VM and geometry engine. Instead, I just >>>>> implemented the simplest lexical scoping rule that I could, which is that >>>>> at the top level of a script, there is only 1 namespace, and the scope of >>>>> every variable and function definition is the entire file (recursive >>>>> scoping). It's simple and consistent: it allows recursive definitions, and >>>>> all you need to know as a user is that the order of definitions doesn't >>>>> matter. Plus, it is well known how to implement this. If I consistently >>>>> used "sequential scoping" for everything, then recursive function >>>>> definitions would be impossible. The actual scoping rules for OpenSCAD are >>>>> apparently very complicated, and I don't know how to implement them using >>>>> conventional compiler technology. >>>>> >>>>> I think it would be beneficial if OpenSCAD were changed so that it >>>>> actually is lexically scoped, except for $ variables. And I'd like to see >>>>> the OpenSCAD team document the lexical scoping rules. In particular, what >>>>> is the scope of a variable definition? Then maybe at a later date I could >>>>> revisit this and try to write a compiler that obeys these rules. >>>>> >>>>> Well defined lexical scoping rules are important for implementing >>>>> first class function values. An anonymous function literal "captures" the >>>>> values of nonlocal lexically scoped variables from surrounding scopes, at >>>>> the time the function literal is evaluated. This results in a data >>>>> structure called a closure. When the function value is subsequently called, >>>>> it uses the captured values. Function definitions work exactly the same >>>>> way: nonlocal variables are captured when the function definition is >>>>> evaluated. The variables that are captured are the ones visible at the >>>>> point where the function is defined, not at the point where the function is >>>>> called. >>>>> >>>>> On 18 November 2016 at 05:38, nop head <nop.head@gmail.com> wrote: >>>>> >>>>>> If you replace the calls of f() with a then you get the same result >>>>>> and it makes sense since the first a refers to the outer scope and the >>>>>> second one to the inner scope. So the function behaves more like a macro >>>>>> text substitution. But if you move the definition of f outside the module >>>>>> it always accesses the outer a. >>>>>> >>>>>> So yes it is a strange mixture of lexical and dynamic. I thought >>>>>> scope was supposed to be lexical apart from the $ variables? >>>>>> >>>>>> On 18 November 2016 at 06:12, otto <otto@123phase.com> wrote: >>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> > doug.moen wrote >>>>>>> > > 1 a = 0; >>>>>>> > > 2 module m() >>>>>>> > > 3 { >>>>>>> > > 4 function f() = a; >>>>>>> > > 5 x = f(); >>>>>>> > > 6 a = 1; >>>>>>> > > 7 y = f(); >>>>>>> > > 8 echo(x,y); >>>>>>> > > 9 } >>>>>>> > > 10 m(); >>>>>>> > > >>>>>>> > > So the output is: >>>>>>> > > ECHO: 0,1 >>>>>>> > > >>>>>>> > > Fun question: is any of this behaviour a bug? >>>>>>> >>>>>>> I think it is. Heres why. >>>>>>> function f() = a; //refers to the outer scope value of a. >>>>>>> x = f(); //sets local x to the outer scope value of a. >>>>>>> a=1; //This should have no effect on the outer >>>>>>> scope. >>>>>>> >>>>>>> function f()=a; should persistently point to outer value. The >>>>>>> fact that function f()=a; created a local variable named with >>>>>>> token_id "a" is an artifact. >>>>>>> >>>>>>> In my opinion >>>>>>> a = 1; >>>>>>> a = 2; //should at least produce a warning if not an error. >>>>>>> >>>>>>> Whereas: >>>>>>> >>>>>>> a=1; >>>>>>> module m() >>>>>>> { >>>>>>> a=2; >>>>>>> } >>>>>>> >>>>>>> should be legal and provides for a different value of a in the >>>>>>> two different scopes as it does now. >>>>>>> >>>>>>> a = 1; >>>>>>> function f() = a; >>>>>>> >>>>>>> Sets the value of "a" as a local variable. The function then >>>>>>> always points to the local variable. We should provide a >>>>>>> warning if it >>>>>>> is redefined. >>>>>>> >>>>>>> Of course, since this is the behavior and it works, it isn't really a >>>>>>> bug, it is an artifact. But it falls into the category of a gotchya, >>>>>>> I can think of no case where there isn't a clearer method of writing >>>>>>> this code. Everywhere this artifact is used, it tends to obfuscate. >>>>>>> >>>>>>> Regards >>>>>>> Otto >>>>>>> >>>>>>> > >>>>>>> > That makes perfect sense, if you want it the other way you do >>>>>>> > >>>>>>> > >>>>>>> > > a = 0; >>>>>>> > > module m() >>>>>>> > > { >>>>>>> > > a = 1; >>>>>>> > > function f() = a; >>>>>>> > > x = f(); >>>>>>> > > y = f(); >>>>>>> > > echo(x,y); >>>>>>> > > } >>>>>>> > > m(); >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > ----- >>>>>>> > Admin - PM me if you need anything, or if I've done something >>>>>>> > stupid... >>>>>>> > >>>>>>> > Unless specifically shown otherwise above, my contribution is in >>>>>>> the >>>>>>> > Public Domain; to the extent possible under law, I have waived all >>>>>>> > copyright and related or neighbouring rights to this work. >>>>>>> Obviously >>>>>>> > inclusion of works of previous authors is not included in the >>>>>>> above. >>>>>>> > >>>>>>> > The TPP is no simple “trade agreement.” Fight it! >>>>>>> > http://www.ourfairdeal.org/ time is running out! -- >>>>>>> > View this message in context: >>>>>>> > http://forum.openscad.org/feedback-let-echo-and-assert-in-ex >>>>>>> pressions-tp19111p19205.html >>>>>>> > Sent from the OpenSCAD mailing list archive at Nabble.com. >>>>>>> > >>>>>>> > _______________________________________________ >>>>>>> > OpenSCAD mailing list >>>>>>> > Discuss@lists.openscad.org >>>>>>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.ope >>>>>>> nscad.org >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> OpenSCAD mailing list >>>>>>> Discuss@lists.openscad.org >>>>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.ope >>>>>>> nscad.org >>>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> OpenSCAD mailing list >>>>>> 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 >>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> 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 >> >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
DM
doug moen
Fri, Nov 18, 2016 5:16 PM

Marius wrote: "I’m not sure anyone wants to document these rules as they’re
mostly artifacts of poorly written/tested code"

I didn't mean document the current behaviour. I mean document the lexical
scoping rules that you would like OpenSCAD to have, so that deviations from
these rules can be reported as bugs, and so that users understand what
behaviour to expect in the future, based on the document.

On 18 November 2016 at 10:39, Marius Kintel marius@kintel.net wrote:

On Nov 18, 2016, at 08:51, doug moen doug@moens.org wrote:

I think it would be beneficial if OpenSCAD were changed so that it

actually is lexically scoped, except for $ variables.

I agree. I’d like to see a way of providing very clear messages to people
exploiting this behavior that it’s deprecated, ideally with a way of
upgrading code to follow the new rules.

And I'd like to see the OpenSCAD team document the lexical scoping

rules. In particular, what is the scope of a variable definition? Then
maybe at a later date I could revisit this and try to write a compiler that
obeys these rules.

I’m not sure anyone wants to document these rules as they’re mostly
artifacts of poorly written/tested code in the past. Extracting docs from
code is not always easy..
Most of this is implicitly available as tests. Any new compiler could
reuse these test cases.
Rather than documenting it, we could always identify usage of such with
tests, and write rules on the AST level to detect usage of said features,
and potentially provide an upgrade path.

-Marius


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

Marius wrote: "I’m not sure anyone wants to document these rules as they’re mostly artifacts of poorly written/tested code" I didn't mean document the current behaviour. I mean document the lexical scoping rules that you would like OpenSCAD to have, so that deviations from these rules can be reported as bugs, and so that users understand what behaviour to expect in the future, based on the document. On 18 November 2016 at 10:39, Marius Kintel <marius@kintel.net> wrote: > > On Nov 18, 2016, at 08:51, doug moen <doug@moens.org> wrote: > > > > I think it would be beneficial if OpenSCAD were changed so that it > actually is lexically scoped, except for $ variables. > > I agree. I’d like to see a way of providing very clear messages to people > exploiting this behavior that it’s deprecated, ideally with a way of > upgrading code to follow the new rules. > > > And I'd like to see the OpenSCAD team document the lexical scoping > rules. In particular, what is the scope of a variable definition? Then > maybe at a later date I could revisit this and try to write a compiler that > obeys these rules. > > > I’m not sure anyone wants to document these rules as they’re mostly > artifacts of poorly written/tested code in the past. Extracting docs from > code is not always easy.. > Most of this is implicitly available as tests. Any new compiler could > reuse these test cases. > Rather than documenting it, we could always identify usage of such with > tests, and write rules on the AST level to detect usage of said features, > and potentially provide an upgrade path. > > -Marius > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
MK
Marius Kintel
Fri, Nov 18, 2016 7:51 PM

On Nov 18, 2016, at 12:16, doug moen doug@moens.org wrote:

I didn't mean document the current behaviour. I mean document the lexical scoping rules that you would like OpenSCAD to have, so that deviations from these rules can be reported as bugs, and so that users understand what behaviour to expect in the future, based on the document.

That would be a good step.
There are two types of current behaviors though, the ones we could deprecate to force people to use a better alternative and the one we’d need to change as there is no better alternative.

Leaking of parameter list into module scope is an example of the former.
Reassignment rules for variables is an example of the latter.

-Marius

> On Nov 18, 2016, at 12:16, doug moen <doug@moens.org> wrote: > > I didn't mean document the current behaviour. I mean document the lexical scoping rules that you would like OpenSCAD to have, so that deviations from these rules can be reported as bugs, and so that users understand what behaviour to expect in the future, based on the document. > That would be a good step. There are two types of current behaviors though, the ones we could deprecate to force people to use a better alternative and the one we’d need to change as there is no better alternative. Leaking of parameter list into module scope is an example of the former. Reassignment rules for variables is an example of the latter. -Marius
M
MichaelAtOz
Sat, Nov 19, 2016 12:31 AM

nophead wrote

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition can
override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That is very useful, particularly with library code. Have a look at
Write.scad, for example.

Also when designing variants, being able to override specific values in a
module.

I previously mentioned that ~hundred lines of variables. If had to declare
them all in all modules, just so I can override them then it would be a
nightmare. Where I can just:

some_module(...,thingID=thingID-0.1);

for any of the many variables.

I have for example a variable number of widgets in a row on a mounting
plate, some face one direction some others, some are on the bottom of the
plate.
I can control any specific behaviour of the specific widget in the calling
module by adjusting any variable/'parameter' on the specific module call.

Anyway, my 2c worth.

Or I just put '$' in all variables...


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19233.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

nophead wrote > I just remembered the truly bizarre rule where putting a variable > assignment in a module call that is not named in the module definition can > override the same name in another module. E.g. > > b = 2; > module x(a) echo(a,b); > > x(1); > x(1, b = 3); > > ECHO: 1, 2 > > ECHO: 1, 3 That is very useful, particularly with library code. Have a look at Write.scad, for example. Also when designing variants, being able to override specific values in a module. I previously mentioned that ~hundred lines of variables. If had to declare them all in all modules, just so I can override them then it would be a nightmare. Where I can just: some_module(...,thingID=thingID-0.1); for any of the many variables. I have for example a variable number of widgets in a row on a mounting plate, some face one direction some others, some are on the bottom of the plate. I can control any specific behaviour of the specific widget in the calling module by adjusting any variable/'parameter' on the specific module call. Anyway, my 2c worth. Or I just put '$' in all variables... ----- Admin - PM me if you need anything, or if I've done something stupid... Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19233.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Sat, Nov 19, 2016 10:20 AM

Well other languages don't allow bizarre overrides like that and I have
never had any problem programming anything with them. I can also make
complex machines like Mendel90 without "hundred lines of variables". The
trick is to use an object oriented style where objects are represented by
lists of properties and passed as a single argument. Anything else is
passed as named parameters apart from a few global variables like layer
height and filament width.

On 19 November 2016 at 00:31, MichaelAtOz oz.at.michael@gmail.com wrote:

nophead wrote

I just remembered the truly bizarre rule where putting a variable
assignment in a module call that is not named in the module definition

can

override the same name in another module. E.g.

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2

ECHO: 1, 3

That is very useful, particularly with library code. Have a look at
Write.scad, for example.

Also when designing variants, being able to override specific values in a
module.

I previously mentioned that ~hundred lines of variables. If had to declare
them all in all modules, just so I can override them then it would be a
nightmare. Where I can just:

some_module(...,thingID=thingID-0.1);

for any of the many variables.

I have for example a variable number of widgets in a row on a mounting
plate, some face one direction some others, some are on the bottom of the
plate.
I can control any specific behaviour of the specific widget in the calling
module by adjusting any variable/'parameter' on the specific module call.

Anyway, my 2c worth.

Or I just put '$' in all variables...


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19233.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Well other languages don't allow bizarre overrides like that and I have never had any problem programming anything with them. I can also make complex machines like Mendel90 without "hundred lines of variables". The trick is to use an object oriented style where objects are represented by lists of properties and passed as a single argument. Anything else is passed as named parameters apart from a few global variables like layer height and filament width. On 19 November 2016 at 00:31, MichaelAtOz <oz.at.michael@gmail.com> wrote: > nophead wrote > > I just remembered the truly bizarre rule where putting a variable > > assignment in a module call that is not named in the module definition > can > > override the same name in another module. E.g. > > > > b = 2; > > module x(a) echo(a,b); > > > > x(1); > > x(1, b = 3); > > > > ECHO: 1, 2 > > > > ECHO: 1, 3 > > That is very useful, particularly with library code. Have a look at > Write.scad, for example. > > Also when designing variants, being able to override specific values in a > module. > > I previously mentioned that ~hundred lines of variables. If had to declare > them all in all modules, just so I can override them then it would be a > nightmare. Where I can just: > > some_module(...,thingID=thingID-0.1); > > for any of the many variables. > > I have for example a variable number of widgets in a row on a mounting > plate, some face one direction some others, some are on the bottom of the > plate. > I can control any specific behaviour of the specific widget in the calling > module by adjusting any variable/'parameter' on the specific module call. > > Anyway, my 2c worth. > > Or I just put '$' in all variables... > > > > > > > ----- > Admin - PM me if you need anything, or if I've done something stupid... > > Unless specifically shown otherwise above, my contribution is in the > Public Domain; to the extent possible under law, I have waived all > copyright and related or neighbouring rights to this work. Obviously > inclusion of works of previous authors is not included in the above. > > The TPP is no simple “trade agreement.” Fight it! > http://www.ourfairdeal.org/ time is running out! > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19233.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
P
Parkinbot
Sat, Nov 19, 2016 11:59 AM

doug.moen wrote

For example,
K = L concat M;
This is easy enough to implement. Would we really need anything more
complicated than this?

Infix notation might be a good step forward to escape the bracket forest and
to increase readability. I don't think a good parser will need backticks for
disambiguation, but this is just the details.

doug.moen wrote

Operator overloading is a huge leap in complexity from defining new
operators. That presupposes the ability to define new user defined data
types. Do we really need this?

Aren't the user defined structs you propose a first step into this
direction? As this introduces only implicit typing, a lot of the potential
of having structs in a language will lie idle. And it is of course not too
complicated to implement an explicit typing system on top of this and I
promise that this will be the first thing users acquainted with OOP will do

  • in a wild fashion. How? Just introduce a common field to carry type
    information and provide "typed" operations to test for it (which sooner or
    later would bring up the demand for a user defined error or at least
    warning, but isn't this already a big miss?).

function myTypeOp(parameters) = if (parameters.type != "myType")
error("myTypeOp called with wrong parameter") else ...

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19243.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > For example, > K = L `concat` M; > This is easy enough to implement. Would we really need anything more > complicated than this? Infix notation might be a good step forward to escape the bracket forest and to increase readability. I don't think a good parser will need backticks for disambiguation, but this is just the details. doug.moen wrote > Operator *overloading* is a huge leap in complexity from defining new > operators. That presupposes the ability to define new user defined data > types. Do we really need this? Aren't the user defined structs you propose a first step into this direction? As this introduces only implicit typing, a lot of the potential of having structs in a language will lie idle. And it is of course not too complicated to implement an explicit typing system on top of this and I promise that this will be the first thing users acquainted with OOP will do - in a wild fashion. How? Just introduce a common field to carry type information and provide "typed" operations to test for it (which sooner or later would bring up the demand for a user defined error or at least warning, but isn't this already a big miss?). > function myTypeOp(parameters) = if (parameters.type != "myType") > error("myTypeOp called with wrong parameter") else ... -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19243.html Sent from the OpenSCAD mailing list archive at Nabble.com.
M
MichaelAtOz
Sun, Nov 20, 2016 3:43 AM

nophead wrote

I can also make complex machines like Mendel90 without "hundred lines of
variables".

Mine is not unlike your Mendel config.scad.

And, yes mine was a design began many years ago on,  and allowed to
organically evolve in a time constrained delivery window...(it's not
pretty).

It used naming conventions to 'class'ify things.

But it would help if the language had structure elements to assist, rather
than having to invent ... anyway, I'm sure we all have our wish lists.

But that 'feature' is really handy for prototyping...


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19258.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

nophead wrote > I can also make complex machines like Mendel90 without "hundred lines of > variables". Mine is not unlike your Mendel config.scad. And, yes mine was a design began many years ago on, and allowed to organically evolve in a time constrained delivery window...(it's not pretty). It used naming conventions to 'class'ify things. But it would help if the language had structure elements to assist, rather than having to invent ... anyway, I'm sure we all have our wish lists. But that 'feature' is really handy for prototyping... ----- Admin - PM me if you need anything, or if I've done something stupid... Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19258.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
runsun
Sun, Nov 20, 2016 6:38 AM

nophead wrote

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2
ECHO: 1, 3

I am shocked to see this is possible. The module x doesn't not define b as
its argument, therefore it shouldn't be allowed to take it, let along change
it. This violates all the programming language studies I had before.


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19260.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

nophead wrote > b = 2; > module x(a) echo(a,b); > > x(1); > x(1, b = 3); > > ECHO: 1, 2 > ECHO: 1, 3 I am shocked to see this is possible. The module x doesn't not define b as its argument, therefore it shouldn't be allowed to take it, let along change it. This violates all the programming language studies I had before. ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19260.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
runsun
Sun, Nov 20, 2016 6:48 AM

A further test rescues myself from the shock. The b in x(a, b=3) is a local,
and only when missing will the global b is involved. Still a bit strange but
not that weird after all.


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf )

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19261.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

A further test rescues myself from the shock. The b in x(a, b=3) is a local, and only when missing will the global b is involved. Still a bit strange but not that weird after all. ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on AWS ( pdf ) -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19261.html Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Sun, Nov 20, 2016 7:10 AM

parkinbot wrote:

Aren't the user defined structs you propose a first step into this
direction? As this introduces only implicit typing, a lot of the potential
of having structs in a language will lie idle. And it is of course not too
complicated to implement an explicit typing system on top of this and I
promise that this will be the first thing users acquainted with OOP will do

  • in a wild fashion. How? Just introduce a common field to carry type
    information and provide "typed" operations to test for it (which sooner or
    later would bring up the demand for a user defined error or at least
    warning, but isn't this already a big miss?).

function myTypeOp(parameters) = if (parameters.type != "myType")
error("myTypeOp called with wrong parameter") else ...

I'm a big fan of user defined errors; they are important for debuggability.
Torsten has already implemented assert in the snapshot, and I'm
happy about that.

As for faking a type system using record fields. Well yes I am planning to
do something like that in my new geometry library. And I will be using
assertions to report "type errors".

I'm not convinced that traditional "OOP with classes" is actually the right
tool for the job. I've been an OOP programmer for a long time, and I no
longer have any romantic ideas about it. It's a powerful tool, but it's also
overly complicated and has problems and limitations.

What I actually need is the ability to classify geometric shapes along
multiple independent axes. The Javascript built-in typeof operator,
for example, doesn't help with this at all.

I plan to represent geometric shapes as records. I can classify shapes
by storing values in record fields. I can test if a shape has a specific
property by querying if it defines a specific named field, or if that field
contains a specific value. These tests will be encapsulated in functions
like is_polytope(), which tests if a shape is a polygon or polyhedron with
vertex information available at preview time. (E.g., union and intersection
do
not compute vertex information at preview time.) Once you've established
that a shape has a particular property, then you can safely access
the record fields associated with that property.

The question is whether OOP with classes, or some similar scheme,
would actually make my library code so much easier to write and maintain
that it would be worth the cost and complexity of implementing OOP.
I'm betting the answer is no, but we'll see.

Abstract theorizing can only take you so far. For me, the discipline
of writing working code, debugging it, refactoring it until it is clean,
always seems to lead to a somewhat different destination than where
I thought I was going.

So I'm not going to implement a full OOP system just in case I happen
to need it for my geometry library. Instead, my plan is to write the
simplest
code that works, and see where that leads. And I think that keeping
the language small and simple is important for useability.

On 19 November 2016 at 06:59, Parkinbot rudolf@parkinbot.com wrote:

doug.moen wrote

For example,
K = L concat M;
This is easy enough to implement. Would we really need anything more
complicated than this?

Infix notation might be a good step forward to escape the bracket forest
and
to increase readability. I don't think a good parser will need backticks
for
disambiguation, but this is just the details.

doug.moen wrote

Operator overloading is a huge leap in complexity from defining new
operators. That presupposes the ability to define new user defined data
types. Do we really need this?

Aren't the user defined structs you propose a first step into this
direction? As this introduces only implicit typing, a lot of the potential
of having structs in a language will lie idle. And it is of course not too
complicated to implement an explicit typing system on top of this and I
promise that this will be the first thing users acquainted with OOP will do

  • in a wild fashion. How? Just introduce a common field to carry type
    information and provide "typed" operations to test for it (which sooner or
    later would bring up the demand for a user defined error or at least
    warning, but isn't this already a big miss?).

function myTypeOp(parameters) = if (parameters.type != "myType")
error("myTypeOp called with wrong parameter") else ...

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19243.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

parkinbot wrote: > > Aren't the user defined structs you propose a first step into this > direction? As this introduces only implicit typing, a lot of the potential > of having structs in a language will lie idle. And it is of course not too > complicated to implement an explicit typing system on top of this and I > promise that this will be the first thing users acquainted with OOP will do > - in a wild fashion. How? Just introduce a common field to carry type > information and provide "typed" operations to test for it (which sooner or > later would bring up the demand for a user defined error or at least > warning, but isn't this already a big miss?). > > function myTypeOp(parameters) = if (parameters.type != "myType") > > error("myTypeOp called with wrong parameter") else ... I'm a big fan of user defined errors; they are important for debuggability. Torsten has already implemented `assert` in the snapshot, and I'm happy about that. As for faking a type system using record fields. Well yes I am planning to do something like that in my new geometry library. And I will be using assertions to report "type errors". I'm not convinced that traditional "OOP with classes" is actually the right tool for the job. I've been an OOP programmer for a long time, and I no longer have any romantic ideas about it. It's a powerful tool, but it's also overly complicated and has problems and limitations. What I actually need is the ability to classify geometric shapes along multiple independent axes. The Javascript built-in `typeof` operator, for example, doesn't help with this at all. I plan to represent geometric shapes as records. I can classify shapes by storing values in record fields. I can test if a shape has a specific property by querying if it defines a specific named field, or if that field contains a specific value. These tests will be encapsulated in functions like is_polytope(), which tests if a shape is a polygon or polyhedron with vertex information available at preview time. (E.g., union and intersection do not compute vertex information at preview time.) Once you've established that a shape has a particular property, then you can safely access the record fields associated with that property. The question is whether OOP with classes, or some similar scheme, would actually make my library code so much easier to write and maintain that it would be worth the cost and complexity of implementing OOP. I'm betting the answer is no, but we'll see. Abstract theorizing can only take you so far. For me, the discipline of writing working code, debugging it, refactoring it until it is clean, always seems to lead to a somewhat different destination than where I thought I was going. So I'm not going to implement a full OOP system just in case I happen to need it for my geometry library. Instead, my plan is to write the simplest code that works, and see where that leads. And I think that keeping the language small and simple is important for useability. On 19 November 2016 at 06:59, Parkinbot <rudolf@parkinbot.com> wrote: > doug.moen wrote > > For example, > > K = L `concat` M; > > This is easy enough to implement. Would we really need anything more > > complicated than this? > > Infix notation might be a good step forward to escape the bracket forest > and > to increase readability. I don't think a good parser will need backticks > for > disambiguation, but this is just the details. > > > doug.moen wrote > > Operator *overloading* is a huge leap in complexity from defining new > > operators. That presupposes the ability to define new user defined data > > types. Do we really need this? > > Aren't the user defined structs you propose a first step into this > direction? As this introduces only implicit typing, a lot of the potential > of having structs in a language will lie idle. And it is of course not too > complicated to implement an explicit typing system on top of this and I > promise that this will be the first thing users acquainted with OOP will do > - in a wild fashion. How? Just introduce a common field to carry type > information and provide "typed" operations to test for it (which sooner or > later would bring up the demand for a user defined error or at least > warning, but isn't this already a big miss?). > > > > function myTypeOp(parameters) = if (parameters.type != "myType") > > error("myTypeOp called with wrong parameter") else ... > > > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19243.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
DM
doug moen
Sun, Nov 20, 2016 7:42 AM

Functions have the same behaviour:

b = 2;
function x(a) = [a,b];
echo(x(1));      // ECHO: [1,2]
echo(x(1, b=3)); // ECHO: [1,3]

Marius has said that he doesn't like people writing code like this, and
that this is a bug he'd like to fix.

Also, there is an open issue about the fact that OpenSCAD fails to report
that you have passed a bad argument to a function or module:

https://github.com/openscad/openscad/issues/1574

If we fix issue 1574, then we will also remove the "feature" that passing
bad named parameters to a module or function causes weird dynamic scoping
behaviour. I am in favour of fixing 1574.

If you really want the function 'x' to accept an optional b= argument, then
the right way to code it is like this:

b = 2;
function x(a, b=b) = [a,b];
echo(x(1));      // ECHO: [1,2]
echo(x(1, b=3)); // ECHO: [1,3]

So I think that fixing 1574 is not a big deal.

On 20 November 2016 at 01:38, runsun runsun@gmail.com wrote:

nophead wrote

b = 2;
module x(a) echo(a,b);

x(1);
x(1, b = 3);

ECHO: 1, 2
ECHO: 1, 3

I am shocked to see this is possible. The module x doesn't not define b as
its argument, therefore it shouldn't be allowed to take it, let along
change
it. This violates all the programming language studies I had before.


$  Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),
runscad.py ( 2 , git ), synwrite ( 2 );   $ tips: hash ( 2 ), matrix (
2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid ,
animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont ,
tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg ,
tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on
AWS ( pdf )

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19260.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Functions have the same behaviour: b = 2; function x(a) = [a,b]; echo(x(1)); // ECHO: [1,2] echo(x(1, b=3)); // ECHO: [1,3] Marius has said that he doesn't like people writing code like this, and that this is a bug he'd like to fix. Also, there is an open issue about the fact that OpenSCAD fails to report that you have passed a bad argument to a function or module: https://github.com/openscad/openscad/issues/1574 If we fix issue 1574, then we will also remove the "feature" that passing bad named parameters to a module or function causes weird dynamic scoping behaviour. I am in favour of fixing 1574. If you really want the function 'x' to accept an optional b= argument, then the right way to code it is like this: b = 2; function x(a, b=b) = [a,b]; echo(x(1)); // ECHO: [1,2] echo(x(1, b=3)); // ECHO: [1,3] So I think that fixing 1574 is not a big deal. On 20 November 2016 at 01:38, runsun <runsun@gmail.com> wrote: > nophead wrote > > b = 2; > > module x(a) echo(a,b); > > > > x(1); > > x(1, b = 3); > > > > ECHO: 1, 2 > > ECHO: 1, 3 > > I am shocked to see this is possible. The module x doesn't not define b as > its argument, therefore it shouldn't be allowed to take it, let along > change > it. This violates all the programming language studies I had before. > > > > > > > ----- > > $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ), > runscad.py ( 2 , git ), synwrite ( 2 ); &nbsp; $ tips: hash ( 2 ), matrix ( > 2 , 3 ), sweep ( 2 , 3 ), var ( 2 ), lerp , animation ( gif , prodVid , > animlib ), precision ( 2 ), xl-control , type , rounded polygon , chfont , > tailRecur ( 2, 3 ), isosphere ( 2 ), area , vol/center , RGB , CurvedImg , > tests ( 2 ), text , triang ; $ Apps: rollApp , blockscad , openjscad , on > AWS ( pdf ) > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19260.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
M
MichaelAtOz
Sun, Nov 20, 2016 12:49 PM

doug.moen wrote

Also, there is an open issue about the fact that OpenSCAD fails to report
that you have passed a bad argument to a function or module:

https://github.com/openscad/openscad/issues/1574

If we fix issue 1574, then we will also remove the "feature" that passing
bad named parameters to a module or function causes weird dynamic scoping
behaviour. I am in favour of fixing 1574.
...
So I think that fixing 1574 is not a big deal.

So we go from OpenSCAD 'silently' failing (as it does for very many cases),
i.e. ignoring bad grammar, to it slapping you in the face?

As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK
probably one of the more wide spread libraries, b. all those others which
took write.scad as an example.

At most 'fixing' should be a warning.

Write.scad extract, one of many examples:
Call:
writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw);
Definition:
module writecircle(text,where,radius){

If you really want the function 'x' to accept an optional b= argument,
then the right way to code it is like this:

So if I want to accept all possible variables...
Does this 'fix' also apply to '$' special variables? So $fn etc will also
fail?

Further food for thought, how does that apply to children()?


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19264.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > Also, there is an open issue about the fact that OpenSCAD fails to report > that you have passed a bad argument to a function or module: > > https://github.com/openscad/openscad/issues/1574 > > If we fix issue 1574, then we will also remove the "feature" that passing > bad named parameters to a module or function causes weird dynamic scoping > behaviour. I am in favour of fixing 1574. > ... > So I think that fixing 1574 is not a big deal. So we go from OpenSCAD 'silently' failing (as it does for very many cases), i.e. ignoring bad grammar, to it slapping you in the face? As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK probably one of the more wide spread libraries, b. all those others which took write.scad as an example. At most 'fixing' should be a warning. Write.scad extract, one of many examples: Call: writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t, space=space,east=east,west=west,middle=middle,ccw=ccw); Definition: module writecircle(text,where,radius){ > If you really want the function 'x' to accept an optional b= argument, > then the right way to code it is like this: So if I want to accept all possible variables... Does this 'fix' also apply to '$' special variables? So $fn etc will also fail? Further food for thought, how does that apply to children()? ----- Admin - PM me if you need anything, or if I've done something stupid... Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19264.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Sun, Nov 20, 2016 1:19 PM

Isn't it trivial to fix write.scad et al by adding the missing parameters
as Doug showed?

The $variables need to work as they do know.

On 20 November 2016 at 12:49, MichaelAtOz oz.at.michael@gmail.com wrote:

doug.moen wrote

Also, there is an open issue about the fact that OpenSCAD fails to report
that you have passed a bad argument to a function or module:

https://github.com/openscad/openscad/issues/1574

If we fix issue 1574, then we will also remove the "feature" that passing
bad named parameters to a module or function causes weird dynamic scoping
behaviour. I am in favour of fixing 1574.
...
So I think that fixing 1574 is not a big deal.

So we go from OpenSCAD 'silently' failing (as it does for very many cases),
i.e. ignoring bad grammar, to it slapping you in the face?

As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK
probably one of the more wide spread libraries, b. all those others which
took write.scad as an example.

At most 'fixing' should be a warning.

Write.scad extract, one of many examples:
Call:
writecircle(text,where+[0,0,height/2],radius-h,rotate=
rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw);
Definition:
module writecircle(text,where,radius){

If you really want the function 'x' to accept an optional b= argument,
then the right way to code it is like this:

So if I want to accept all possible variables...
Does this 'fix' also apply to '$' special variables? So $fn etc will also
fail?

Further food for thought, how does that apply to children()?


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19264.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Isn't it trivial to fix write.scad et al by adding the missing parameters as Doug showed? The $variables need to work as they do know. On 20 November 2016 at 12:49, MichaelAtOz <oz.at.michael@gmail.com> wrote: > doug.moen wrote > > Also, there is an open issue about the fact that OpenSCAD fails to report > > that you have passed a bad argument to a function or module: > > > > https://github.com/openscad/openscad/issues/1574 > > > > If we fix issue 1574, then we will also remove the "feature" that passing > > bad named parameters to a module or function causes weird dynamic scoping > > behaviour. I am in favour of fixing 1574. > > ... > > So I think that fixing 1574 is not a big deal. > > So we go from OpenSCAD 'silently' failing (as it does for very many cases), > i.e. ignoring bad grammar, to it slapping you in the face? > > As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK > probably one of the more wide spread libraries, b. all those others which > took write.scad as an example. > > At most 'fixing' should be a warning. > > Write.scad extract, one of many examples: > Call: > writecircle(text,where+[0,0,height/2],radius-h,rotate= > rotate,font=font,h=h,t=t, > space=space,east=east,west=west,middle=middle,ccw=ccw); > Definition: > module writecircle(text,where,radius){ > > > > If you really want the function 'x' to accept an optional b= argument, > > then the right way to code it is like this: > > So if I want to accept all possible variables... > Does this 'fix' also apply to '$' special variables? So $fn etc will also > fail? > > Further food for thought, how does that apply to children()? > > > > > > ----- > Admin - PM me if you need anything, or if I've done something stupid... > > Unless specifically shown otherwise above, my contribution is in the > Public Domain; to the extent possible under law, I have waived all > copyright and related or neighbouring rights to this work. Obviously > inclusion of works of previous authors is not included in the above. > > The TPP is no simple “trade agreement.” Fight it! > http://www.ourfairdeal.org/ time is running out! > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19264.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DM
doug moen
Sun, Nov 20, 2016 2:14 PM

MichaelAtOz said fixing issue 1574 will break "write.scad", unless we only
issue warnings for bad labeled arguments in user defined functions and
modules.

Thanks, that's useful information, and I'll add it to the github issue.

Further food for thought, how does that apply to children()?

What do you mean?

On 20 November 2016 at 07:49, MichaelAtOz oz.at.michael@gmail.com wrote:

doug.moen wrote

Also, there is an open issue about the fact that OpenSCAD fails to report
that you have passed a bad argument to a function or module:

https://github.com/openscad/openscad/issues/1574

If we fix issue 1574, then we will also remove the "feature" that passing
bad named parameters to a module or function causes weird dynamic scoping
behaviour. I am in favour of fixing 1574.
...
So I think that fixing 1574 is not a big deal.

So we go from OpenSCAD 'silently' failing (as it does for very many cases),
i.e. ignoring bad grammar, to it slapping you in the face?

As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK
probably one of the more wide spread libraries, b. all those others which
took write.scad as an example.

At most 'fixing' should be a warning.

Write.scad extract, one of many examples:
Call:
writecircle(text,where+[0,0,height/2],radius-h,rotate=
rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw);
Definition:
module writecircle(text,where,radius){

If you really want the function 'x' to accept an optional b= argument,
then the right way to code it is like this:

So if I want to accept all possible variables...
Does this 'fix' also apply to '$' special variables? So $fn etc will also
fail?

Further food for thought, how does that apply to children()?


Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the
Public Domain; to the extent possible under law, I have waived all
copyright and related or neighbouring rights to this work. Obviously
inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it!
http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19264.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

MichaelAtOz said fixing issue 1574 will break "write.scad", unless we only issue warnings for bad labeled arguments in user defined functions and modules. Thanks, that's useful information, and I'll add it to the github issue. > Further food for thought, how does that apply to children()? What do you mean? On 20 November 2016 at 07:49, MichaelAtOz <oz.at.michael@gmail.com> wrote: > doug.moen wrote > > Also, there is an open issue about the fact that OpenSCAD fails to report > > that you have passed a bad argument to a function or module: > > > > https://github.com/openscad/openscad/issues/1574 > > > > If we fix issue 1574, then we will also remove the "feature" that passing > > bad named parameters to a module or function causes weird dynamic scoping > > behaviour. I am in favour of fixing 1574. > > ... > > So I think that fixing 1574 is not a big deal. > > So we go from OpenSCAD 'silently' failing (as it does for very many cases), > i.e. ignoring bad grammar, to it slapping you in the face? > > As I pointed out earlier 'fixing' this will break a. write.scad, AFAIK > probably one of the more wide spread libraries, b. all those others which > took write.scad as an example. > > At most 'fixing' should be a warning. > > Write.scad extract, one of many examples: > Call: > writecircle(text,where+[0,0,height/2],radius-h,rotate= > rotate,font=font,h=h,t=t, > space=space,east=east,west=west,middle=middle,ccw=ccw); > Definition: > module writecircle(text,where,radius){ > > > > If you really want the function 'x' to accept an optional b= argument, > > then the right way to code it is like this: > > So if I want to accept all possible variables... > Does this 'fix' also apply to '$' special variables? So $fn etc will also > fail? > > Further food for thought, how does that apply to children()? > > > > > > ----- > Admin - PM me if you need anything, or if I've done something stupid... > > Unless specifically shown otherwise above, my contribution is in the > Public Domain; to the extent possible under law, I have waived all > copyright and related or neighbouring rights to this work. Obviously > inclusion of works of previous authors is not included in the above. > > The TPP is no simple “trade agreement.” Fight it! > http://www.ourfairdeal.org/ time is running out! > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19264.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
R
Ronaldo
Sun, Nov 20, 2016 6:47 PM

I am not sure that this is pertinent to this discussion but it is sometimes
so hard to debug as issue 1574. I have just crossed with it and isolated it
in the code (using version 2015.03-2):

d = [ [0,0], [1,1], [1,0] ];
d3 = 2*[for(v=d) [v[0], v[1], 1]];
n=12; // well defined

d1 = [for(i=[0:n]) [0,1,0] ];
d2 = d1; // well defined
d3 = d2; // redefinition

d = [for(i=[0:n]) [0,0,-1] ]; // redefinition

The console ouput:

Saved backup file:
C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad
Compiling design (CSG Tree generation)...
WARNING: Ignoring unknown variable 'n'.
WARNING: Ignoring unknown variable 'd2'.
Compiling design (CSG Products generation)...
Geometries in cache: 1
Geometry cache size in bytes: 728
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 0 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 0 seconds

--
View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19272.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I am not sure that this is pertinent to this discussion but it is sometimes so hard to debug as issue 1574. I have just crossed with it and isolated it in the code (using version 2015.03-2): > d = [ [0,0], [1,1], [1,0] ]; > d3 = 2*[for(v=d) [v[0], v[1], 1]]; > n=12; // well defined > > d1 = [for(i=[0:n]) [0,1,0] ]; > d2 = d1; // well defined > d3 = d2; // redefinition > > d = [for(i=[0:n]) [0,0,-1] ]; // redefinition The console ouput: > Saved backup file: > C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad > Compiling design (CSG Tree generation)... > WARNING: Ignoring unknown variable 'n'. > WARNING: Ignoring unknown variable 'd2'. > Compiling design (CSG Products generation)... > Geometries in cache: 1 > Geometry cache size in bytes: 728 > CGAL Polyhedrons in cache: 0 > CGAL cache size in bytes: 0 > Compiling design (CSG Products normalization)... > Normalized CSG tree has 0 elements > Compile and preview finished. > Total rendering time: 0 hours, 0 minutes, 0 seconds -- View this message in context: http://forum.openscad.org/feedback-let-echo-and-assert-in-expressions-tp19111p19272.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Sun, Nov 20, 2016 7:04 PM

Yes the second definition of d3 needs d2, which needs d1 which needs n but
it gets moved to where the first definition of d3 is where they are not in
scope.

On 20 November 2016 at 18:47, Ronaldo rcmpersiano@gmail.com wrote:

I am not sure that this is pertinent to this discussion but it is sometimes
so hard to debug as issue 1574. I have just crossed with it and isolated it
in the code (using version 2015.03-2):

d = [ [0,0], [1,1], [1,0] ];
d3 = 2*[for(v=d) [v[0], v[1], 1]];
n=12; // well defined

d1 = [for(i=[0:n]) [0,1,0] ];
d2 = d1; // well defined
d3 = d2; // redefinition

d = [for(i=[0:n]) [0,0,-1] ]; // redefinition

The console ouput:

Saved backup file:
C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad
Compiling design (CSG Tree generation)...
WARNING: Ignoring unknown variable 'n'.
WARNING: Ignoring unknown variable 'd2'.
Compiling design (CSG Products generation)...
Geometries in cache: 1
Geometry cache size in bytes: 728
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 0 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 0 seconds

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19272.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

Yes the second definition of d3 needs d2, which needs d1 which needs n but it gets moved to where the first definition of d3 is where they are not in scope. On 20 November 2016 at 18:47, Ronaldo <rcmpersiano@gmail.com> wrote: > I am not sure that this is pertinent to this discussion but it is sometimes > so hard to debug as issue 1574. I have just crossed with it and isolated it > in the code (using version 2015.03-2): > > > d = [ [0,0], [1,1], [1,0] ]; > > d3 = 2*[for(v=d) [v[0], v[1], 1]]; > > n=12; // well defined > > > > d1 = [for(i=[0:n]) [0,1,0] ]; > > d2 = d1; // well defined > > d3 = d2; // redefinition > > > > d = [for(i=[0:n]) [0,0,-1] ]; // redefinition > > The console ouput: > > > Saved backup file: > > C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad > > Compiling design (CSG Tree generation)... > > WARNING: Ignoring unknown variable 'n'. > > WARNING: Ignoring unknown variable 'd2'. > > Compiling design (CSG Products generation)... > > Geometries in cache: 1 > > Geometry cache size in bytes: 728 > > CGAL Polyhedrons in cache: 0 > > CGAL cache size in bytes: 0 > > Compiling design (CSG Products normalization)... > > Normalized CSG tree has 0 elements > > Compile and preview finished. > > Total rendering time: 0 hours, 0 minutes, 0 seconds > > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19272.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Sun, Nov 20, 2016 7:18 PM

And to help the user it complaints of n and d2?

2016-11-20 17:04 GMT-02:00 nop head nop.head@gmail.com:

Yes the second definition of d3 needs d2, which needs d1 which needs n but
it gets moved to where the first definition of d3 is where they are not in
scope.

And to help the user it complaints of n and d2? 2016-11-20 17:04 GMT-02:00 nop head <nop.head@gmail.com>: > Yes the second definition of d3 needs d2, which needs d1 which needs n but > it gets moved to where the first definition of d3 is where they are not in > scope. > > >
TP
Torsten Paul
Sun, Nov 20, 2016 7:24 PM

On 11/20/2016 08:18 PM, Ronaldo Persiano wrote:

And to help the user it complaints of n and d2?

Well, this has been discussed to death in various slightly
different cases. The problem is that ideally the reassignment
should warn or even better throw an error. But at this time
it would break pretty much all cases where "-D" is used
from command line.

I have no idea if that was done by intention or just a
coincidence when the "-D" flag was introduced, but replacing
the assignment where it was listed first makes the simple
"just add all the -D stuff at the end of the script"
possible.

So, yes, it's an ugly bug. But it's not trivial to fix.

ciao,
Torsten.

On 11/20/2016 08:18 PM, Ronaldo Persiano wrote: > And to help the user it complaints of n and d2? > Well, this has been discussed to death in various slightly different cases. The problem is that ideally the reassignment should warn or even better throw an error. But at this time it would break pretty much all cases where "-D" is used from command line. I have no idea if that was done by intention or just a coincidence when the "-D" flag was introduced, but replacing the assignment where it was listed first makes the simple "just add all the -D stuff at the end of the script" possible. So, yes, it's an ugly bug. But it's not trivial to fix. ciao, Torsten.
DM
doug moen
Sun, Nov 20, 2016 8:37 PM

The OpenSCAD scoping rules are terrible. Really hard to understand. The
worst I've seen in any language.

I fixed this in my next-gen OpenSCAD prototype. I have a different scoping
rule for definitions at the top level of a script. The scope of every
variable, function and module definition is the entire file. The order in
which you write definitions doesn't matter. (Aside from redefinitions of
the same name, obviously.) This scoping rule is very simple, easy to
understand (the order of definitions doesn't matter), and it fixes the
problem Ronaldo describes.

I think that, for the top level of a script, this is backwards compatible.
This problem normally only bites people at the top level, so fixing the
problem at the top level is a win.

On 20 November 2016 at 13:47, Ronaldo rcmpersiano@gmail.com wrote:

I am not sure that this is pertinent to this discussion but it is sometimes
so hard to debug as issue 1574. I have just crossed with it and isolated it
in the code (using version 2015.03-2):

d = [ [0,0], [1,1], [1,0] ];
d3 = 2*[for(v=d) [v[0], v[1], 1]];
n=12; // well defined

d1 = [for(i=[0:n]) [0,1,0] ];
d2 = d1; // well defined
d3 = d2; // redefinition

d = [for(i=[0:n]) [0,0,-1] ]; // redefinition

The console ouput:

Saved backup file:
C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad
Compiling design (CSG Tree generation)...
WARNING: Ignoring unknown variable 'n'.
WARNING: Ignoring unknown variable 'd2'.
Compiling design (CSG Products generation)...
Geometries in cache: 1
Geometry cache size in bytes: 728
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 0 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 0 seconds

--
View this message in context: http://forum.openscad.org/
feedback-let-echo-and-assert-in-expressions-tp19111p19272.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


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

The OpenSCAD scoping rules are terrible. Really hard to understand. The worst I've seen in any language. I fixed this in my next-gen OpenSCAD prototype. I have a different scoping rule for definitions at the top level of a script. The scope of every variable, function and module definition is the entire file. The order in which you write definitions doesn't matter. (Aside from redefinitions of the same name, obviously.) This scoping rule is very simple, easy to understand (the order of definitions doesn't matter), and it fixes the problem Ronaldo describes. I think that, for the top level of a script, this is backwards compatible. This problem normally only bites people at the top level, so fixing the problem at the top level is a win. On 20 November 2016 at 13:47, Ronaldo <rcmpersiano@gmail.com> wrote: > I am not sure that this is pertinent to this discussion but it is sometimes > so hard to debug as issue 1574. I have just crossed with it and isolated it > in the code (using version 2015.03-2): > > > d = [ [0,0], [1,1], [1,0] ]; > > d3 = 2*[for(v=d) [v[0], v[1], 1]]; > > n=12; // well defined > > > > d1 = [for(i=[0:n]) [0,1,0] ]; > > d2 = d1; // well defined > > d3 = d2; // redefinition > > > > d = [for(i=[0:n]) [0,0,-1] ]; // redefinition > > The console ouput: > > > Saved backup file: > > C:/Users/ronaldo/Documents/OpenSCAD/backups/unsaved-backup-gqHp8824.scad > > Compiling design (CSG Tree generation)... > > WARNING: Ignoring unknown variable 'n'. > > WARNING: Ignoring unknown variable 'd2'. > > Compiling design (CSG Products generation)... > > Geometries in cache: 1 > > Geometry cache size in bytes: 728 > > CGAL Polyhedrons in cache: 0 > > CGAL cache size in bytes: 0 > > Compiling design (CSG Products normalization)... > > Normalized CSG tree has 0 elements > > Compile and preview finished. > > Total rendering time: 0 hours, 0 minutes, 0 seconds > > > > > > -- > View this message in context: http://forum.openscad.org/ > feedback-let-echo-and-assert-in-expressions-tp19111p19272.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >