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