JB
Jordan Brown
Fri, Jan 23, 2026 4:38 AM
Thus it is impossible to have tail call elimination because you can't even represent calls!
Indeed, the CSG tree must include all of the nodes.
But that doesn’t mean that the program that generates it has to have a stack frame for every level of tree. If the “tree” that it generates is degenerate, e.g.
union() {
cube(1);
union() {
cube(2);
…
}
}
Then it can be generated by a tail-recursion-eliminated routine.
> Thus it is impossible to have tail call elimination because you can't even represent calls!
Indeed, the CSG tree must include all of the nodes.
But that doesn’t mean that the program that generates it has to have a stack frame for every level of tree. If the “tree” that it generates is degenerate, e.g.
union() {
cube(1);
union() {
cube(2);
…
}
}
Then it can be generated by a tail-recursion-eliminated routine.
R
Rudolf
Fri, Jan 23, 2026 10:39 AM
Why not use the old hull() trick?
s = 50;
p = [for(x=[-s, s], y=[-s, s], z=[-s, s]) if(!(x==50&&y==50&&z==50))
[x,y,z]];
hull() polyhedron(p, [[0,1,2,3,4,5,6]]);
Am 22.01.2026 um 10:44 schrieb Curt McDowell via Discuss:
Here's my entry. Although it's vanilla code, it's just about as
readable as a polyhedron()!
difference() {
union() {
translate([-1, 0, 0]) cube([2, 1, 1]);
translate([-1, 0, 1]) cube(1);
}
translate([1, 1, 1] * 2 / 3)
rotate([0, atan(sqrt(2)), 45])
translate([-2, -2, 0]) cube(4);
}
difference() {
translate([-1, 1, 0]) cube([2, 1, 1]);
translate([0, 0, 1]) rotate([0, 45, 0]) cube(3);
}
Anyone else notice that /command line/ OpenSCAD can't parse original
attachment because it is UTF-8 (has the UTF-8 prefix) ?
$ openscad --version
OpenSCAD version 2026.01.02
$ openscad "MarkStoddard Block.scad" /*<=== Opens window and
displays correctly*/
$ openscad "MarkStoddard Block.scad" -o out.stl
ERROR: Parser error: syntax error in file MarkStoddard Block.scad,
line 1
Can't parse file 'MarkStoddard Block.scad'!
$ dos2unix "MarkStoddard Block.scad"
dos2unix: converting file MarkStoddard Block.scad to Unix format...
$ openscad "MarkStoddard Block.scad" -o out.stl
Geometries in cache: 17
Geometry cache size in bytes: 17672
CGAL Polyhedrons in cache: 2
CGAL cache size in bytes: 0
Total rendering time: 0:00:00.023
Top level object is a 3D object (manifold):
Status: NoError
Genus: 0
Vertices: 18
Facets: 32
If one edits the file in OpenSCAD, the file is saved back as ASCII.
After that it can be processed from the command line. (If one edits
the file in Emacs or Vim, the file is saved back as UTF-8.)
Possible bug 1: should be able to process a UTF-8 file from the
command line (at the very least, ignore the prefix)
Possible bug 2: should be able to edit a UTF-8 file and save it back
as UTF-8 (a bigger can of worms)
-Curt
On 1/21/26 05:30, William F. Adams via Discuss wrote:
Why not use the old hull() trick?
s = 50;
p = [for(x=[-s, s], y=[-s, s], z=[-s, s]) if(!(x==50&&y==50&&z==50))
[x,y,z]];
hull() polyhedron(p, [[0,1,2,3,4,5,6]]);
Am 22.01.2026 um 10:44 schrieb Curt McDowell via Discuss:
>
> Here's my entry. Although it's vanilla code, it's just about as
> readable as a polyhedron()!
>
> difference() {
> union() {
> translate([-1, 0, 0]) cube([2, 1, 1]);
> translate([-1, 0, 1]) cube(1);
> }
>
> translate([1, 1, 1] * 2 / 3)
> rotate([0, atan(sqrt(2)), 45])
> translate([-2, -2, 0]) cube(4);
> }
>
> difference() {
> translate([-1, 1, 0]) cube([2, 1, 1]);
> translate([0, 0, 1]) rotate([0, 45, 0]) cube(3);
> }
>
> Anyone else notice that /command line/ OpenSCAD can't parse original
> attachment because it is UTF-8 (has the UTF-8 prefix) ?
>
> $ openscad --version
> OpenSCAD version 2026.01.02
> $ openscad "MarkStoddard Block.scad" /*<=== Opens window and
> displays correctly*/
> $ openscad "MarkStoddard Block.scad" -o out.stl
> ERROR: Parser error: syntax error in file MarkStoddard Block.scad,
> line 1
> Can't parse file 'MarkStoddard Block.scad'!
>
> $ dos2unix "MarkStoddard Block.scad"
> dos2unix: converting file MarkStoddard Block.scad to Unix format...
> $ openscad "MarkStoddard Block.scad" -o out.stl
> Geometries in cache: 17
> Geometry cache size in bytes: 17672
> CGAL Polyhedrons in cache: 2
> CGAL cache size in bytes: 0
> Total rendering time: 0:00:00.023
> Top level object is a 3D object (manifold):
> Status: NoError
> Genus: 0
> Vertices: 18
> Facets: 32
>
> If one edits the file in OpenSCAD, the file is saved back as ASCII.
> After that it can be processed from the command line. (If one edits
> the file in Emacs or Vim, the file is saved back as UTF-8.)
>
> Possible bug 1: should be able to process a UTF-8 file from the
> command line (at the very least, ignore the prefix)
> Possible bug 2: should be able to edit a UTF-8 file and save it back
> as UTF-8 (a bigger can of worms)
>
> -Curt
>
> On 1/21/26 05:30, William F. Adams via Discuss wrote:
>> This was recently put up on Reddit:
>>
>> https://old.reddit.com/r/FreeCAD/comments/1qibk1y/fun_freecad_model_to_try_to_build/
>>
>>
>>
>> I believe I got it in Block/OpenSCAD, ~20 minutes:
>>
>> https://www.blockscad3d.com/community/projects/2052961
>>
>> click on a "Create" button to make an STL to check (or see the attached .scad file).
>>
>> Is there a simpler/better way to make this?
>>
>> Maybe using BOSL2?
>>
>> William
>>
>> _______________________________________________
>> OpenSCAD mailing list
>> To unsubscribe send an email todiscuss-leave@lists.openscad.org
>
> _______________________________________________
> OpenSCAD mailing list
> To unsubscribe send an email todiscuss-leave@lists.openscad.org
RW
Rogier Wolff
Fri, Jan 23, 2026 1:23 PM
Father Horton wasn't asking ABOUT tail recursion, but "what /is/ tail
recursion".
If we have a function:
int fib (n)
{
if (n < 2) return 1;
return fib (n-1) + fib (n-2);
}
this function uses recursion. Normally when fib calls itself for the
fib (n-1) call, the compiler will have to create a new location for
the "n" variable, and call "fib" and then throw away the space for "n"
again. This is recursion.
On the other hand, when the call "fib (n-2)" is reached, the compiler
could simply follow the same procedure... But now something smart is
possible too: you can simply calculate "n-2", and then simply JUMP to
the start of the "fib fuction". It will do its thing and (eventually)
return something. This saves the allocating/deallocating space for a
new version of "n". This saves time and space.
This optimization isn't always possible.... I think my example is one:
after the fib (n-2) result is calculated, there is still some work to
do. So this can only be optimized if the function would end in
return fib (...);
Anyway, apparently there are enough interesting cases where it makes
sense that some compilers will perform this optimization for you.
Roger.
On Thu, Jan 22, 2026 at 05:15:29PM -0600, Father Horton via Discuss wrote:
That's why I put a question mark. I don't know.
On Thu, Jan 22, 2026 at 4:54 PM Adrian Mariano avm4@cornell.edu wrote:
Do modules get special handling of tail recursion?
On Thu, Jan 22, 2026 at 5:50 PM Father Horton fatherhorton@gmail.com
wrote:
On 1/22/2026 11:25 AM, Adrian Mariano wrote:
The question: what can you get with 45 deg rotations around the x, y and
z axes?
An additional constraint: my probably-wrong intuition says you should
be able to do it with no more than three rotations, zero or one in each of
the axes. (-45 rotations are OK.) That's a fairly small number; maybe
I'll put it together.
Note as an aside, is there no way to increase allowed recursion depth?
If I set the max much higher it fails with "recursion detected" (like I
didn't know).
At least one of the limits, maybe the only limit, is based on the
compiled-in C++ stack size. OpenSCAD recursion translates into C++
recursion, so that's a hard limit. (But: I don't know about the APIs
involved here, but at least some thread APIs let you specify the stack size
for newly created threads, so that might allow for customization.)
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
Father Horton wasn't asking ABOUT tail recursion, but "what /is/ tail
recursion".
If we have a function:
int fib (n)
{
if (n < 2) return 1;
return fib (n-1) + fib (n-2);
}
this function uses recursion. Normally when fib calls itself for the
fib (n-1) call, the compiler will have to create a new location for
the "n" variable, and call "fib" and then throw away the space for "n"
again. This is recursion.
On the other hand, when the call "fib (n-2)" is reached, the compiler
could simply follow the same procedure... But now something smart is
possible too: you can simply calculate "n-2", and then simply JUMP to
the start of the "fib fuction". It will do its thing and (eventually)
return something. This saves the allocating/deallocating space for a
new version of "n". This saves time and space.
This optimization isn't always possible.... I think my example is one:
after the fib (n-2) result is calculated, there is still some work to
do. So this can only be optimized if the function would end in
return fib (...);
Anyway, apparently there are enough interesting cases where it makes
sense that some compilers will perform this optimization for you.
Roger.
On Thu, Jan 22, 2026 at 05:15:29PM -0600, Father Horton via Discuss wrote:
> That's why I put a question mark. I don't know.
>
> On Thu, Jan 22, 2026 at 4:54 PM Adrian Mariano <avm4@cornell.edu> wrote:
>
> > Do modules get special handling of tail recursion?
> >
> > On Thu, Jan 22, 2026 at 5:50 PM Father Horton <fatherhorton@gmail.com>
> > wrote:
> >
> >> Tail recursion?
> >>
> >> On Thu, Jan 22, 2026 at 1:35 PM Jordan Brown via Discuss <
> >> discuss@lists.openscad.org> wrote:
> >>
> >>> On 1/22/2026 11:25 AM, Adrian Mariano wrote:
> >>>
> >>> The question: what can you get with 45 deg rotations around the x, y and
> >>> z axes?
> >>>
> >>>
> >>> An additional constraint: my probably-wrong intuition says you should
> >>> be able to do it with no more than three rotations, zero or one in each of
> >>> the axes. (-45 rotations are OK.) That's a fairly small number; maybe
> >>> I'll put it together.
> >>>
> >>> Note as an aside, is there no way to increase allowed recursion depth?
> >>> If I set the max much higher it fails with "recursion detected" (like I
> >>> didn't know).
> >>>
> >>>
> >>> At least one of the limits, maybe the only limit, is based on the
> >>> compiled-in C++ stack size. OpenSCAD recursion translates into C++
> >>> recursion, so that's a hard limit. (But: I don't know about the APIs
> >>> involved here, but at least some thread APIs let you specify the stack size
> >>> for newly created threads, so that might allow for customization.)
> >>>
> >>> _______________________________________________
> >>> 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
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
FH
Father Horton
Fri, Jan 23, 2026 3:39 PM
I was asking whether it applied. I know what it is 🙂
On Fri, Jan 23, 2026 at 7:23 AM Rogier Wolff R.E.Wolff@bitwizard.nl wrote:
Father Horton wasn't asking ABOUT tail recursion, but "what /is/ tail
recursion".
If we have a function:
int fib (n)
{
if (n < 2) return 1;
return fib (n-1) + fib (n-2);
}
this function uses recursion. Normally when fib calls itself for the
fib (n-1) call, the compiler will have to create a new location for
the "n" variable, and call "fib" and then throw away the space for "n"
again. This is recursion.
On the other hand, when the call "fib (n-2)" is reached, the compiler
could simply follow the same procedure... But now something smart is
possible too: you can simply calculate "n-2", and then simply JUMP to
the start of the "fib fuction". It will do its thing and (eventually)
return something. This saves the allocating/deallocating space for a
new version of "n". This saves time and space.
This optimization isn't always possible.... I think my example is one:
after the fib (n-2) result is calculated, there is still some work to
do. So this can only be optimized if the function would end in
return fib (...);
Anyway, apparently there are enough interesting cases where it makes
sense that some compilers will perform this optimization for you.
Roger.
On Thu, Jan 22, 2026 at 05:15:29PM -0600, Father Horton via Discuss wrote:
That's why I put a question mark. I don't know.
On Thu, Jan 22, 2026 at 4:54 PM Adrian Mariano avm4@cornell.edu wrote:
Do modules get special handling of tail recursion?
On Thu, Jan 22, 2026 at 5:50 PM Father Horton fatherhorton@gmail.com
wrote:
On 1/22/2026 11:25 AM, Adrian Mariano wrote:
The question: what can you get with 45 deg rotations around the x, y
z axes?
An additional constraint: my probably-wrong intuition says you
be able to do it with no more than three rotations, zero or one in
the axes. (-45 rotations are OK.) That's a fairly small number;
I'll put it together.
Note as an aside, is there no way to increase allowed recursion
If I set the max much higher it fails with "recursion detected"
didn't know).
At least one of the limits, maybe the only limit, is based on the
compiled-in C++ stack size. OpenSCAD recursion translates into C++
recursion, so that's a hard limit. (But: I don't know about the
involved here, but at least some thread APIs let you specify the
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110
**
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
I was asking whether it applied. I know what it is 🙂
On Fri, Jan 23, 2026 at 7:23 AM Rogier Wolff <R.E.Wolff@bitwizard.nl> wrote:
> Father Horton wasn't asking ABOUT tail recursion, but "what /is/ tail
> recursion".
>
> If we have a function:
>
> int fib (n)
> {
> if (n < 2) return 1;
> return fib (n-1) + fib (n-2);
> }
>
> this function uses recursion. Normally when fib calls itself for the
> fib (n-1) call, the compiler will have to create a new location for
> the "n" variable, and call "fib" and then throw away the space for "n"
> again. This is recursion.
>
> On the other hand, when the call "fib (n-2)" is reached, the compiler
> could simply follow the same procedure... But now something smart is
> possible too: you can simply calculate "n-2", and then simply JUMP to
> the start of the "fib fuction". It will do its thing and (eventually)
> return something. This saves the allocating/deallocating space for a
> new version of "n". This saves time and space.
>
> This optimization isn't always possible.... I think my example is one:
> after the fib (n-2) result is calculated, there is still some work to
> do. So this can only be optimized if the function would end in
> return fib (...);
>
> Anyway, apparently there are enough interesting cases where it makes
> sense that some compilers will perform this optimization for you.
>
> Roger.
>
> On Thu, Jan 22, 2026 at 05:15:29PM -0600, Father Horton via Discuss wrote:
> > That's why I put a question mark. I don't know.
> >
> > On Thu, Jan 22, 2026 at 4:54 PM Adrian Mariano <avm4@cornell.edu> wrote:
> >
> > > Do modules get special handling of tail recursion?
> > >
> > > On Thu, Jan 22, 2026 at 5:50 PM Father Horton <fatherhorton@gmail.com>
> > > wrote:
> > >
> > >> Tail recursion?
> > >>
> > >> On Thu, Jan 22, 2026 at 1:35 PM Jordan Brown via Discuss <
> > >> discuss@lists.openscad.org> wrote:
> > >>
> > >>> On 1/22/2026 11:25 AM, Adrian Mariano wrote:
> > >>>
> > >>> The question: what can you get with 45 deg rotations around the x, y
> and
> > >>> z axes?
> > >>>
> > >>>
> > >>> An additional constraint: my probably-wrong intuition says you
> should
> > >>> be able to do it with no more than three rotations, zero or one in
> each of
> > >>> the axes. (-45 rotations are OK.) That's a fairly small number;
> maybe
> > >>> I'll put it together.
> > >>>
> > >>> Note as an aside, is there no way to increase allowed recursion
> depth?
> > >>> If I set the max much higher it fails with "recursion detected"
> (like I
> > >>> didn't know).
> > >>>
> > >>>
> > >>> At least one of the limits, maybe the only limit, is based on the
> > >>> compiled-in C++ stack size. OpenSCAD recursion translates into C++
> > >>> recursion, so that's a hard limit. (But: I don't know about the
> APIs
> > >>> involved here, but at least some thread APIs let you specify the
> stack size
> > >>> for newly created threads, so that might allow for customization.)
> > >>>
> > >>> _______________________________________________
> > >>> 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
>
>
> --
> ** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110
> **
> ** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
> ** KVK: 27239233 **
> f equals m times a. When your f is steady, and your m is going down
> your a** is going up. -- Chris Hadfield about flying up the space shuttle.
> ** 'a' for accelleration.
>
JB
Jordan Brown
Fri, Jan 23, 2026 6:09 PM
On 1/23/2026 2:39 AM, Rudolf via Discuss wrote:
Why not use the old hull() trick?
s = 50;
p = [for(x=[-s, s], y=[-s, s], z=[-s, s]) if(!(x==50&&y==50&&z==50))
[x,y,z]];
hull() polyhedron(p, [[0,1,2,3,4,5,6]]);
Indeed, but whether that's more or less understandable than the
straightforward polyhedron is unclear. It's also kind of an abuse of
polyhedron(), which will eventually bit us if we ever want to have
polyhedron() check its inputs for validity.
On 1/23/2026 2:39 AM, Rudolf via Discuss wrote:
>
> Why not use the old hull() trick?
>
> s = 50;
> p = [for(x=[-s, s], y=[-s, s], z=[-s, s]) if(!(x==50&&y==50&&z==50))
> [x,y,z]];
> hull() polyhedron(p, [[0,1,2,3,4,5,6]]);
>
Indeed, but whether that's more or less understandable than the
straightforward polyhedron is unclear. It's also kind of an abuse of
polyhedron(), which will eventually bit us if we ever want to have
polyhedron() check its inputs for validity.