discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

is color an actual operator module ?

V
vulcan_@mac.com
Mon, Jul 28, 2025 11:18 PM

ir is i just a low priority operator like echo and assert?

ir is i just a low priority operator like echo and assert?
JB
Jordan Brown
Mon, Jul 28, 2025 11:36 PM

On 7/28/2025 4:18 PM, vulcan_--- via Discuss wrote:

ir is i just a low priority operator like echo and assert?

Colors is an actual operator module.

There are only three of the "special" expression operators:  let, echo,
assert.
They are similar to, but different from, the operator modules let, echo,
and assert.
And those are different from the list comprehension module let.

On 7/28/2025 4:18 PM, vulcan_--- via Discuss wrote: > > ir is i just a low priority operator like echo and assert? > Colors is an actual operator module. There are only three of the "special" expression operators:  let, echo, assert. They are similar to, but different from, the operator modules let, echo, and assert. And those are different from the list comprehension module let.
V
vulcan_@mac.com
Wed, Jul 30, 2025 7:38 PM

oi

so when i a statement do i need to be concerned that i dont know if (let echo assert) are operators or modules?

if i write

xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator in an expression so, as it is inside parens to force precedence right?

but

assert( true ) translate( [1,1,1] ) cube(); // here it is an operator module, yes?

are there any differences in operation between operator and  module forms of (let echo assert) ?

are there any syntactic differences in how they are used in a script?

oi so when i a statement do i need to be concerned that i dont know if (let echo assert) are operators or modules? if i write xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator in an expression so, as it is inside parens to force precedence right? but assert( true ) translate( \[1,1,1\] ) cube(); // here it is an operator module, yes? are there any differences in operation between operator and module forms of (let echo assert) ? are there any syntactic differences in how they are used in a script?
AM
Adrian Mariano
Wed, Jul 30, 2025 11:32 PM

The execution order is different between modules and expressions, because
expressions run first, before all modules.

If you write this

assert(x>0);  // assert is a module
y=f(x);  // function f requires that x>0
sphere(y);

then your code will fail if x<=0 when f() is evaluated and the assert will
never do anything.  You have to rewrite it as:

dummy = assert(x>0);  // assert is in an expression
y=f(x);
sphere(y);

in order for the assertion to prevent f() from being invoked incorrectly.
I was totally mystified the first time I encountered this behavior and I
could only fix it by moving the assert() into f().  I rarely put an assert
inside an expression that does something else.  It seems less clear and
binds together two things that may not necessarily belong together.  Also
it may not be obvious that you can chain them like dummy = assert(cond1)
assert(cond2) assert(cond3);

On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss <
discuss@lists.openscad.org> wrote:

oi

so when i a statement do i need to be concerned that i dont know if (let
echo assert) are operators or modules?

if i write

xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator in
an expression so, as it is inside parens to force precedence right?

but

assert( true ) translate( [1,1,1] ) cube(); // here it is an operator
module, yes?

are there any differences in operation between operator and module forms
of (let echo assert) ?

are there any syntactic differences in how they are used in a script?


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

The execution order is different between modules and expressions, because expressions run first, before all modules. If you write this assert(x>0); // assert is a module y=f(x); // function f requires that x>0 sphere(y); then your code will fail if x<=0 when f() is evaluated and the assert will never do anything. You have to rewrite it as: dummy = assert(x>0); // assert is in an expression y=f(x); sphere(y); in order for the assertion to prevent f() from being invoked incorrectly. I was totally mystified the first time I encountered this behavior and I could only fix it by moving the assert() into f(). I rarely put an assert inside an expression that does something else. It seems less clear and binds together two things that may not necessarily belong together. Also it may not be obvious that you can chain them like dummy = assert(cond1) assert(cond2) assert(cond3); On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss < discuss@lists.openscad.org> wrote: > oi > > so when i a statement do i need to be concerned that i dont know if (let > echo assert) are operators or modules? > > if i write > > xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator in > an expression so, as it is inside parens to force precedence right? > > but > > assert( true ) translate( [1,1,1] ) cube(); // here it is an operator > module, yes? > > are there any differences in operation between operator and module forms > of (let echo assert) ? > > are there any syntactic differences in how they are used in a script? > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
NH
nop head
Thu, Jul 31, 2025 7:55 AM

I would do:

y = assert(x>0) f(x);

That avoids the dummy variable and makes it clearer why the condition must
hold, i.e. to satisfy f().

On Thu, 31 Jul 2025 at 00:32, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

The execution order is different between modules and expressions, because
expressions run first, before all modules.

If you write this

assert(x>0);  // assert is a module
y=f(x);  // function f requires that x>0
sphere(y);

then your code will fail if x<=0 when f() is evaluated and the assert will
never do anything.  You have to rewrite it as:

dummy = assert(x>0);  // assert is in an expression
y=f(x);
sphere(y);

in order for the assertion to prevent f() from being invoked incorrectly.
I was totally mystified the first time I encountered this behavior and I
could only fix it by moving the assert() into f().  I rarely put an assert
inside an expression that does something else.  It seems less clear and
binds together two things that may not necessarily belong together.  Also
it may not be obvious that you can chain them like dummy = assert(cond1)
assert(cond2) assert(cond3);

On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss <
discuss@lists.openscad.org> wrote:

oi

so when i a statement do i need to be concerned that i dont know if (let
echo assert) are operators or modules?

if i write

xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator
in an expression so, as it is inside parens to force precedence right?

but

assert( true ) translate( [1,1,1] ) cube(); // here it is an operator
module, yes?

are there any differences in operation between operator and module forms
of (let echo assert) ?

are there any syntactic differences in how they are used in a script?


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I would do: y = assert(x>0) f(x); That avoids the dummy variable and makes it clearer why the condition must hold, i.e. to satisfy f(). On Thu, 31 Jul 2025 at 00:32, Adrian Mariano via Discuss < discuss@lists.openscad.org> wrote: > The execution order is different between modules and expressions, because > expressions run first, before all modules. > > If you write this > > assert(x>0); // assert is a module > y=f(x); // function f requires that x>0 > sphere(y); > > then your code will fail if x<=0 when f() is evaluated and the assert will > never do anything. You have to rewrite it as: > > dummy = assert(x>0); // assert is in an expression > y=f(x); > sphere(y); > > in order for the assertion to prevent f() from being invoked incorrectly. > I was totally mystified the first time I encountered this behavior and I > could only fix it by moving the assert() into f(). I rarely put an assert > inside an expression that does something else. It seems less clear and > binds together two things that may not necessarily belong together. Also > it may not be obvious that you can chain them like dummy = assert(cond1) > assert(cond2) assert(cond3); > > > > On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss < > discuss@lists.openscad.org> wrote: > >> oi >> >> so when i a statement do i need to be concerned that i dont know if (let >> echo assert) are operators or modules? >> >> if i write >> >> xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator >> in an expression so, as it is inside parens to force precedence right? >> >> but >> >> assert( true ) translate( [1,1,1] ) cube(); // here it is an operator >> module, yes? >> >> are there any differences in operation between operator and module forms >> of (let echo assert) ? >> >> are there any syntactic differences in how they are used in a script? >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Thu, Jul 31, 2025 10:36 AM

Real examples are not so simple, and it rarely makes sense, at least to
me,  to try to attach the assertion to some specific calculation.  There
may be 5 or 10 assertions checking the validity of input to a module.  And
then there may be a dozen expressions, possibly with different conditions
based on the parameters.  How do I decide which calculation to attach the
assertions to?  Determining at which point invalid input causes a problem
may require effort, and I don't think it's going to increase clarity for
someone reading the code.  In fact, I would argue that it's not trivial to
determine whether you can get away with the module form of assert.  It
requires examining the code to figure out whether anything goes wrong
before the modules run.

Algorithmically the assertions are separate operations, not part of some
computation.  Attaching ten assertions to a computation just makes the code
more confusing and harder to read by mixing assertion and calculation
together and putting a huge space between the variable and the calculation
for that variable.    And if I were to somehow associate each assertion
with a different computation, that would be pretty confusing as well, since
now I have the same problem repeatedly.  Also note that in real code, an
assertion doesn't look like "assert(x>0)", it's 80 characters with some
condition to check and a text error message to display.  The calculation
also doesn't look like "f(x)" but may be a long calculation with
conditionals.

On Thu, Jul 31, 2025 at 3:55 AM nop head via Discuss <
discuss@lists.openscad.org> wrote:

I would do:

y = assert(x>0) f(x);

That avoids the dummy variable and makes it clearer why the condition must
hold, i.e. to satisfy f().

On Thu, 31 Jul 2025 at 00:32, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

The execution order is different between modules and expressions, because
expressions run first, before all modules.

If you write this

assert(x>0);  // assert is a module
y=f(x);  // function f requires that x>0
sphere(y);

then your code will fail if x<=0 when f() is evaluated and the assert
will never do anything.  You have to rewrite it as:

dummy = assert(x>0);  // assert is in an expression
y=f(x);
sphere(y);

in order for the assertion to prevent f() from being invoked
incorrectly.  I was totally mystified the first time I encountered this
behavior and I could only fix it by moving the assert() into f().  I
rarely put an assert inside an expression that does something else.  It
seems less clear and binds together two things that may not necessarily
belong together.  Also it may not be obvious that you can chain them like
dummy = assert(cond1) assert(cond2) assert(cond3);

On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss <
discuss@lists.openscad.org> wrote:

oi

so when i a statement do i need to be concerned that i dont know if (let
echo assert) are operators or modules?

if i write

xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator
in an expression so, as it is inside parens to force precedence right?

but

assert( true ) translate( [1,1,1] ) cube(); // here it is an operator
module, yes?

are there any differences in operation between operator and module forms
of (let echo assert) ?

are there any syntactic differences in how they are used in a script?


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Real examples are not so simple, and it rarely makes sense, at least to me, to try to attach the assertion to some specific calculation. There may be 5 or 10 assertions checking the validity of input to a module. And then there may be a dozen expressions, possibly with different conditions based on the parameters. How do I decide which calculation to attach the assertions to? Determining at which point invalid input causes a problem may require effort, and I don't think it's going to increase clarity for someone reading the code. In fact, I would argue that it's not trivial to determine whether you can get away with the module form of assert. It requires examining the code to figure out whether anything goes wrong before the modules run. Algorithmically the assertions are separate operations, not part of some computation. Attaching ten assertions to a computation just makes the code more confusing and harder to read by mixing assertion and calculation together and putting a huge space between the variable and the calculation for that variable. And if I were to somehow associate each assertion with a different computation, that would be pretty confusing as well, since now I have the same problem repeatedly. Also note that in real code, an assertion doesn't look like "assert(x>0)", it's 80 characters with some condition to check and a text error message to display. The calculation also doesn't look like "f(x)" but may be a long calculation with conditionals. On Thu, Jul 31, 2025 at 3:55 AM nop head via Discuss < discuss@lists.openscad.org> wrote: > I would do: > > y = assert(x>0) f(x); > > That avoids the dummy variable and makes it clearer why the condition must > hold, i.e. to satisfy f(). > > On Thu, 31 Jul 2025 at 00:32, Adrian Mariano via Discuss < > discuss@lists.openscad.org> wrote: > >> The execution order is different between modules and expressions, because >> expressions run first, before all modules. >> >> If you write this >> >> assert(x>0); // assert is a module >> y=f(x); // function f requires that x>0 >> sphere(y); >> >> then your code will fail if x<=0 when f() is evaluated and the assert >> will never do anything. You have to rewrite it as: >> >> dummy = assert(x>0); // assert is in an expression >> y=f(x); >> sphere(y); >> >> in order for the assertion to prevent f() from being invoked >> incorrectly. I was totally mystified the first time I encountered this >> behavior and I could only fix it by moving the assert() into f(). I >> rarely put an assert inside an expression that does something else. It >> seems less clear and binds together two things that may not necessarily >> belong together. Also it may not be obvious that you can chain them like >> dummy = assert(cond1) assert(cond2) assert(cond3); >> >> >> >> On Wed, Jul 30, 2025 at 3:38 PM vulcan_--- via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> oi >>> >>> so when i a statement do i need to be concerned that i dont know if (let >>> echo assert) are operators or modules? >>> >>> if i write >>> >>> xxx= ( assert(true) 2 ) + 3 // i would think this assert is an operator >>> in an expression so, as it is inside parens to force precedence right? >>> >>> but >>> >>> assert( true ) translate( [1,1,1] ) cube(); // here it is an operator >>> module, yes? >>> >>> are there any differences in operation between operator and module forms >>> of (let echo assert) ? >>> >>> are there any syntactic differences in how they are used in a script? >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
V
vulcan_@mac.com
Thu, Jul 31, 2025 3:07 PM

when assert() is a module, is it an operator module or an object module?

my testing:

RGB=[0,0,1];
color("red") assert( RGB == [0,0,1])
translate([0,3,0])
cube(3);

this works, the assert passes and the cube is drawn.
Or i change the test to [0,0,2 ] and the assert fails

color("red")
translate([0,3,0])
cube(3) assert( RGB == [0,0,01]);

emits this:

[WARNING: module cube() does not support child modules in file ., line 14](14,C:/Program Files/OpenSCAD (Nightly))

and draws the red cube

so .. in a limited sense assert() is an operator module

it can be placed so:

assert( RGB == [0,0,2]);

and then it is being an Object Model as it works even when it has no children, which an operator module cannot do.

and it can be a function returning a value and both types of module.

when assert() is a module, is it an operator module or an object module? my testing: `RGB=[0,0,1];`\ `color("red") assert( RGB == [0,0,1])`\ ` translate([0,3,0])`\ ` cube(3);` this works, the assert passes and the cube is drawn.\ Or i change the test to \[0,0,2 \] and the assert fails `color("red") `\ ` translate([0,3,0])`\ ` cube(3) assert( RGB == [0,0,01]);` emits this: [WARNING: module cube() does not support child modules in file ., line 14](14,C:/Program Files/OpenSCAD (Nightly)) and draws the red cube so .. in a limited sense assert() is an operator module it can be placed so: `assert( RGB == [0,0,2]);` and then it is being an Object Model as it works even when it has no children, which an operator module cannot do. and it can be a function returning a value and both types of module.
NH
nop head
Thu, Jul 31, 2025 3:11 PM

There aren't any operator modules. Just modules used in statements and
functions used in expressions. Some are both like assert and echo.

On Thu, 31 Jul 2025, 16:08 vulcan_--- via Discuss, <
discuss@lists.openscad.org> wrote:

when assert() is a module, is it an operator module or an object module?

my testing:

RGB=[0,0,1];
color("red") assert( RGB == [0,0,1])
translate([0,3,0])
cube(3);

this works, the assert passes and the cube is drawn.
Or i change the test to [0,0,2 ] and the assert fails

color("red")
translate([0,3,0])
cube(3) assert( RGB == [0,0,01]);

emits this:

WARNING: module cube() does not support child modules in file ., line 14

and draws the red cube

so .. in a limited sense assert() is an operator module

it can be placed so:

assert( RGB == [0,0,2]);

and then it is being an Object Model as it works even when it has no
children, which an operator module cannot do.

and it can be a function returning a value and both types of module.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

There aren't any operator modules. Just modules used in statements and functions used in expressions. Some are both like assert and echo. On Thu, 31 Jul 2025, 16:08 vulcan_--- via Discuss, < discuss@lists.openscad.org> wrote: > when assert() is a module, is it an operator module or an object module? > > my testing: > > RGB=[0,0,1]; > color("red") assert( RGB == [0,0,1]) > translate([0,3,0]) > cube(3); > > this works, the assert passes and the cube is drawn. > Or i change the test to [0,0,2 ] and the assert fails > > color("red") > translate([0,3,0]) > cube(3) assert( RGB == [0,0,01]); > > emits this: > > WARNING: module cube() does not support child modules in file ., line 14 > > and draws the red cube > > so .. in a limited sense assert() is an operator module > > it can be placed so: > > assert( RGB == [0,0,2]); > > and then it is being an Object Model as it works even when it has no > children, which an operator module cannot do. > > and it can be a function returning a value and both types of module. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Thu, Jul 31, 2025 4:53 PM

I think he is distinguishing between a module like cube which creates
geometry and does not accept children and a module like rotate which
operates on children and doesn’t produce any results itself. It does not
fail without children. It just does not produce a result.

So then cube is an “object” and rotate is an “operator”.

If you want to put the assert module into that framework it’s an operator.
It accepts children like rotate. It does not fail without children.

However the framework is not complete. A module can perfectly well produce
geometry and also process and operate on children.  It just happens that no
built in modules do that.

I don’t think there is ever a reason to give children to assert even though
you can.

On Thu, Jul 31, 2025 at 11:12 nop head via Discuss <
discuss@lists.openscad.org> wrote:

There aren't any operator modules. Just modules used in statements and
functions used in expressions. Some are both like assert and echo.

On Thu, 31 Jul 2025, 16:08 vulcan_--- via Discuss, <
discuss@lists.openscad.org> wrote:

when assert() is a module, is it an operator module or an object module?

my testing:

RGB=[0,0,1];
color("red") assert( RGB == [0,0,1])
translate([0,3,0])
cube(3);

this works, the assert passes and the cube is drawn.
Or i change the test to [0,0,2 ] and the assert fails

color("red")
translate([0,3,0])
cube(3) assert( RGB == [0,0,01]);

emits this:

WARNING: module cube() does not support child modules in file ., line 14

and draws the red cube

so .. in a limited sense assert() is an operator module

it can be placed so:

assert( RGB == [0,0,2]);

and then it is being an Object Model as it works even when it has no
children, which an operator module cannot do.

and it can be a function returning a value and both types of module.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I think he is distinguishing between a module like cube which creates geometry and does not accept children and a module like rotate which operates on children and doesn’t produce any results itself. It does not fail without children. It just does not produce a result. So then cube is an “object” and rotate is an “operator”. If you want to put the assert module into that framework it’s an operator. It accepts children like rotate. It does not fail without children. However the framework is not complete. A module can perfectly well produce geometry and also process and operate on children. It just happens that no built in modules do that. I don’t think there is ever a reason to give children to assert even though you can. On Thu, Jul 31, 2025 at 11:12 nop head via Discuss < discuss@lists.openscad.org> wrote: > There aren't any operator modules. Just modules used in statements and > functions used in expressions. Some are both like assert and echo. > > On Thu, 31 Jul 2025, 16:08 vulcan_--- via Discuss, < > discuss@lists.openscad.org> wrote: > >> when assert() is a module, is it an operator module or an object module? >> >> my testing: >> >> RGB=[0,0,1]; >> color("red") assert( RGB == [0,0,1]) >> translate([0,3,0]) >> cube(3); >> >> this works, the assert passes and the cube is drawn. >> Or i change the test to [0,0,2 ] and the assert fails >> >> color("red") >> translate([0,3,0]) >> cube(3) assert( RGB == [0,0,01]); >> >> emits this: >> >> WARNING: module cube() does not support child modules in file ., line 14 >> >> and draws the red cube >> >> so .. in a limited sense assert() is an operator module >> >> it can be placed so: >> >> assert( RGB == [0,0,2]); >> >> and then it is being an Object Model as it works even when it has no >> children, which an operator module cannot do. >> >> and it can be a function returning a value and both types of module. >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
V
vulcan_@mac.com
Thu, Jul 31, 2025 11:02 PM

while the underlying implementation may be the same for Operator Modules and Object Modules in practice the differences are critical.

If one defines an Object Module it results in one or more shapes being drawn. An Operator Module must end with a call to children() and cannot itself draw shapes.

An operator at the end of a statement causes no error nor warning, but also does nothing. .. at least in the 2025.07.20 i am using

An object can only be at the end of a statement .. sort of

color("red")
cube(5)
translate([0,3,0])
;

this will run but emits a warning: WARNING: module cube() does not support child modules …

but it does draw the cube

This also draws the cube, with the warning, but does not draw the second object, the sphere()

color("red")
cube(5)
translate([0,3,0])
sphere(r=4);

So in real terms, there are

  1. functions that return a value, can only be used in expressions, and cannot draw geometry

  2. modules that draw geometry, must come last in a statement, and cannot call children()

  3. modules that operate on objects can only call other operator modules and must call children() as their last statement

and i have documented all of this after quite a lot of experimentation to be sure i was writing true things about modules

If you folks can correct my understanding of modules where i might be in error i would appreciate it so i can update the docs

thanks

while the underlying implementation may be the same for Operator Modules and Object Modules in practice the differences are critical. If one defines an Object Module it results in one or more shapes being drawn. An Operator Module must end with a call to children() and cannot itself draw shapes. An operator at the end of a statement causes no error nor warning, but also does nothing. .. at least in the 2025.07.20 i am using An object can *only* be at the end of a statement .. sort of `color("red")`\ ` cube(5)`\ ` translate([0,3,0])`\ ` ;` this will run but emits a warning: WARNING: module cube() does not support child modules … but it does draw the cube This also draws the cube, with the warning, but does not draw the second object, the sphere() `color("red")`\ ` cube(5)`\ ` translate([0,3,0])`\ ` sphere(r=4);` So in real terms, there are 1. functions that return a value, can only be used in expressions, and cannot draw geometry 2. modules that draw geometry, must come last in a statement, and cannot call children() 3. modules that operate on objects can only call other operator modules and must call children() as their last statement and i have documented all of this after quite a lot of experimentation to be sure i was writing true things about modules If you folks can correct my understanding of modules where i might be in error i would appreciate it so i can update the docs thanks