discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

TooTallToby CAD challenge

AM
Adrian Mariano
Thu, Jan 22, 2026 10:54 PM

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

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 > >
FH
Father Horton
Thu, Jan 22, 2026 11:15 PM

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

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 >> >>
CM
Curt McDowell
Thu, Jan 22, 2026 11:25 PM

Evidently not, as drawpt is eligible for tail recursion as written.

On 1/22/26 15:15, 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.)
Evidently not, as drawpt is eligible for tail recursion as written. On 1/22/26 15:15, 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.) >
CM
Curt McDowell
Thu, Jan 22, 2026 11:31 PM

Haha. The grand wizard around here is Adrian!

I was able to further obfuscate my solution. Gemini figured out the (1 +
sqrt(3)) / 3) part to remove one translate(). Then I figured out how to
remove three more translate()s, having had to /guess/ the sqrt(2):

difference() {
     union() { cube([2, 1, 1]); cube([1, 1, 2]); }
     translate(2 * [sqrt(2), (1 + sqrt(3)) / 3, (1 + sqrt(3)) / 3])
         rotate([0, atan(sqrt(2)), 45]) cube(4, center=true);
}
difference() {
     cube([2, 2, 1]);
     translate([1, 0, 1]) rotate([0, 45, 0]) cube(3);
}

-Curt

On 1/22/26 01:49, Guenther Sohler via Discuss wrote:

Hey, that's an awesome short.
you are an absolute geometry wizard :)

On Thu, Jan 22, 2026 at 10:44 AM Curt McDowell via Discuss
discuss@lists.openscad.org wrote:

 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);
     }
Haha. The grand wizard around here is Adrian! I was able to further obfuscate my solution. Gemini figured out the (1 + sqrt(3)) / 3) part to remove one translate(). Then I figured out how to remove three more translate()s, having had to /guess/ the sqrt(2): difference() {     union() { cube([2, 1, 1]); cube([1, 1, 2]); }     translate(2 * [sqrt(2), (1 + sqrt(3)) / 3, (1 + sqrt(3)) / 3])         rotate([0, atan(sqrt(2)), 45]) cube(4, center=true); } difference() {     cube([2, 2, 1]);     translate([1, 0, 1]) rotate([0, 45, 0]) cube(3); } -Curt On 1/22/26 01:49, Guenther Sohler via Discuss wrote: > Hey, that's an awesome short. > you are an absolute geometry wizard :) > > On Thu, Jan 22, 2026 at 10:44 AM Curt McDowell via Discuss > <discuss@lists.openscad.org> wrote: > > 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); > } >
AM
Adrian Mariano
Fri, Jan 23, 2026 12:07 AM

The last statement in drawpt is an if() statement, not a recursion.  But I
suspect that modules don't give special handling to tail recursion, even if
more generously interpreted.  I think it's not something that people
normally try to do---thousands deep recursion in a module.  My application
here is rather weird and there's probably a better way to approach the
problem of exploring the group generated by 45 deg rotations.  I just took
a quick/lazy one, figuring that if there was some structure it might pop
out.  It could be rewritten as a function that computes all the points.
That would get tail recursion, and then you could run arbitrarily many
points.  And you could check how close the best match is to [1,1,1].  But
for the picture, looping drawpt() isn't an inferior choice, in terms of
quality of the result.

On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

Evidently not, as drawpt is eligible for tail recursion as written.
On 1/22/26 15:15, 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

The last statement in drawpt is an if() statement, not a recursion. But I suspect that modules don't give special handling to tail recursion, even if more generously interpreted. I think it's not something that people normally try to do---thousands deep recursion in a module. My application here is rather weird and there's probably a better way to approach the problem of exploring the group generated by 45 deg rotations. I just took a quick/lazy one, figuring that if there was some structure it might pop out. It could be rewritten as a function that computes all the points. That would get tail recursion, and then you could run arbitrarily many points. And you could check how close the best match is to [1,1,1]. But for the picture, looping drawpt() isn't an inferior choice, in terms of quality of the result. On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss < discuss@lists.openscad.org> wrote: > Evidently not, as drawpt is eligible for tail recursion as written. > On 1/22/26 15:15, 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
SP
Sanjeev Prabhakar
Fri, Jan 23, 2026 1:10 AM

just with the points list:

a=[[0,0,0],[1,0,0],[1,0,0],[2,0,0],[2,2,0],[0,2,0]];
b=[[0,0,1],[0,0,1],[1,1,1],[2,1,1],[2,2,1],[0,2,1]];
c=[[0,1,1],[1,1,1],[1,1,1],[1,2,1],[0,2,1]];
d=[[0,1,2],[0,1,2],[1,2,2],[1,2,2],[0,2,2]];
s1=[a,b];
s2=[c,d];
color("blue") for(p=[s1,s2,cpo(s1),cpo(s2)]) for(p1=p) p_line3dc(p1,.02);
for(p=[s1,s2]) swp(p);

//module to draw a polyline in 3d space (loop closed)
module p_line3dc(path,d,rec=0,$fn=20){
for(i=[0:len(path)-1])
let(
i_plus=i<len(path)-1?i+1:0
)
hull(){
translate(path[i])if(rec==0)sphere(d/2); else cube(d,true);
translate(path[i_plus])if(rec==0)sphere(d/2);else cube(d,true);
}
}

function faces(sol)=
//    calculate the faces for the vertices with shape l x m with first and
the last end closed
let(
l=len(sol),
m=len(sol[0]),
n1=[for(i=[0:m-1])i],
n2=[for(i=[0:l-2]) each ([ for(j=[0:m-1])
each
j<m-1?[[(j+1)+im,j+im,j+(i+1)m],[(j+1)+im,j+(i+1)m,(j+1)+(i+1)m]]:
[[0+i
m,j+i
m,j+(i+1)m],[0+im,j+(i+1)*m,0+(i+1)*m]]
])],
n3=[for(i=[0:m-1])i+(l-1)*m],
n4=[for(i=[len(n3)-1:-1:0])n3[i]],
n=[n1,each (n2),n4]
)n;

function vertices(sol)=
[each for (p=sol)p];

// module for rendering the polyhedron with ends closed
module swp(sol){
let(
v1=vertices(sol),
f1=faces(sol)
)
polyhedron(v1,f1,convexity=10);
}

//function to change the orientation of points of a prism.
function cpo(prism)=[for(i=[0:len(prism[0])-1])[for(p=prism)p[i]]];

[image: Screenshot 2026-01-23 at 6.39.23 AM.png]

On Wed, 21 Jan 2026 at 19:01, William F. Adams via Discuss <
discuss@lists.openscad.org> 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 to discuss-leave@lists.openscad.org

just with the points list: a=[[0,0,0],[1,0,0],[1,0,0],[2,0,0],[2,2,0],[0,2,0]]; b=[[0,0,1],[0,0,1],[1,1,1],[2,1,1],[2,2,1],[0,2,1]]; c=[[0,1,1],[1,1,1],[1,1,1],[1,2,1],[0,2,1]]; d=[[0,1,2],[0,1,2],[1,2,2],[1,2,2],[0,2,2]]; s1=[a,b]; s2=[c,d]; color("blue") for(p=[s1,s2,cpo(s1),cpo(s2)]) for(p1=p) p_line3dc(p1,.02); for(p=[s1,s2]) swp(p); //module to draw a polyline in 3d space (loop closed) module p_line3dc(path,d,rec=0,$fn=20){ for(i=[0:len(path)-1]) let( i_plus=i<len(path)-1?i+1:0 ) hull(){ translate(path[i])if(rec==0)sphere(d/2); else cube(d,true); translate(path[i_plus])if(rec==0)sphere(d/2);else cube(d,true); } } function faces(sol)= // calculate the faces for the vertices with shape l x m with first and the last end closed let( l=len(sol), m=len(sol[0]), n1=[for(i=[0:m-1])i], n2=[for(i=[0:l-2]) each ([ for(j=[0:m-1]) each j<m-1?[[(j+1)+i*m,j+i*m,j+(i+1)*m],[(j+1)+i*m,j+(i+1)*m,(j+1)+(i+1)*m]]: [[0+i*m,j+i*m,j+(i+1)*m],[0+i*m,j+(i+1)*m,0+(i+1)*m]] ])], n3=[for(i=[0:m-1])i+(l-1)*m], n4=[for(i=[len(n3)-1:-1:0])n3[i]], n=[n1,each (n2),n4] )n; function vertices(sol)= [each for (p=sol)p]; // module for rendering the polyhedron with ends closed module swp(sol){ let( v1=vertices(sol), f1=faces(sol) ) polyhedron(v1,f1,convexity=10); } //function to change the orientation of points of a prism. function cpo(prism)=[for(i=[0:len(prism[0])-1])[for(p=prism)p[i]]]; [image: Screenshot 2026-01-23 at 6.39.23 AM.png] On Wed, 21 Jan 2026 at 19:01, William F. Adams via Discuss < discuss@lists.openscad.org> 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 to discuss-leave@lists.openscad.org
CM
Curt McDowell
Fri, Jan 23, 2026 1:27 AM

There /must/ be an if() for tail recursion or it would never stop. Any
(and multiple) recursive call can be optimized from anywhere within a
function as long as the function immediately returns the results of the
call (in this case children) without doing anything with them.

module drawpt(p,max,count=0)
{
    move(p) sphere(r=.01); /Tail elimination pseudo-code:/
    dir=rand_int(1,3,1)[0];
    if (count<max)                                   if count < max
    drawpt(  dir==0 ? zrot(45,p)                         arg0 = (dir
== 0 ? ...)
           : dir==1 ? xrot(45,p)                         arg1 =
max;  arg2 = count + 1
           : /*dir==2*/  yrot(45,p),max,count+1);        goto top
without popping frame
}                                                   pop frame and
return children

I agree it would be very unusual to need it. More important is that
function() does implement tail recursion!

-Curt

On 1/22/26 16:07, Adrian Mariano via Discuss wrote:

The last statement in drawpt is an if() statement, not a recursion. 
But I suspect that modules don't give special handling to tail
recursion, even if more generously interpreted.  I think it's not
something that people normally try to do---thousands deep recursion in
a module.  My application here is rather weird and there's probably a
better way to approach the problem of exploring the group generated by
45 deg rotations.  I just took a quick/lazy one, figuring that if
there was some structure it might pop out.  It could be rewritten as a
function that computes all the points.  That would get tail recursion,
and then you could run arbitrarily many points.  And you could check
how close the best match is to [1,1,1].  But for the picture, looping
drawpt() isn't an inferior choice, in terms of quality of the result.

On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss
discuss@lists.openscad.org wrote:

 Evidently not, as drawpt is eligible for tail recursion as written.

 On 1/22/26 15:15, 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 todiscuss-leave@lists.openscad.org

There /must/ be an if() for tail recursion or it would never stop. Any (and multiple) recursive call can be optimized from anywhere within a function as long as the function immediately returns the results of the call (in this case children) without doing anything with them. module drawpt(p,max,count=0) {    move(p) sphere(r=.01); /Tail elimination pseudo-code:/    dir=rand_int(1,3,1)[0];    if (count<max)                                   if count < max    drawpt(  dir==0 ? zrot(45,p)                         arg0 = (dir == 0 ? ...)           : dir==1 ? xrot(45,p)                         arg1 = max;  arg2 = count + 1           : /*dir==2*/  yrot(45,p),max,count+1);        goto top without popping frame }                                                   pop frame and return children I agree it would be very unusual to need it. More important is that function() does implement tail recursion! -Curt On 1/22/26 16:07, Adrian Mariano via Discuss wrote: > The last statement in drawpt is an if() statement, not a recursion.  > But I suspect that modules don't give special handling to tail > recursion, even if more generously interpreted.  I think it's not > something that people normally try to do---thousands deep recursion in > a module.  My application here is rather weird and there's probably a > better way to approach the problem of exploring the group generated by > 45 deg rotations.  I just took a quick/lazy one, figuring that if > there was some structure it might pop out.  It could be rewritten as a > function that computes all the points.  That would get tail recursion, > and then you could run arbitrarily many points.  And you could check > how close the best match is to [1,1,1].  But for the picture, looping > drawpt() isn't an inferior choice, in terms of quality of the result. > > On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss > <discuss@lists.openscad.org> wrote: > > Evidently not, as drawpt is eligible for tail recursion as written. > > On 1/22/26 15:15, 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 todiscuss-leave@lists.openscad.org
CM
Curt McDowell
Fri, Jan 23, 2026 1:27 AM

Jordan,

When we rotate [1, 0, 0] we could hope to arrive at [1, 1, 1] * √3 / 3
using only rotations of 45 degrees, But I don't believe it's possible.
Every matrix representing a rotation by 45 is in the Abelian matrix
field /M3 ℚ(√2//)/ because /sin(45) = cos(45) = //√2 / 2. S/o
regardless of how many multiplies, a coordinate could never occur that
is a multiple of √3.

Thanks for filing #6555 https://github.com/openscad/openscad/issues/6555!

-Curt

On 1/22/26 10:38, Jordan Brown via Discuss wrote:

On 1/22/2026 9:48 AM, Adrian Mariano via Discuss wrote:

Jordan, BOSL2 will help you avoid that trig and decrease the required
thinking as shown below.  :)

Thanks, and I agree that's more obvious, but it's still unsatisfying
that it's not a sequence of 45° rotates.  It probably can't be such
a sequence, but it should be.

Jordan, When we rotate [1, 0, 0] we could hope to arrive at [1, 1, 1] * √3 / 3 using only rotations of 45 degrees, But I don't believe it's possible. Every matrix representing a rotation by 45 is in the Abelian matrix field */M3 ℚ(√2/*/*)*/ because /sin(45) = cos(45) = //√2 / 2. S/o regardless of how many multiplies, a coordinate could never occur that is a multiple of √3. Thanks for filing #6555 <https://github.com/openscad/openscad/issues/6555>! -Curt On 1/22/26 10:38, Jordan Brown via Discuss wrote: > On 1/22/2026 9:48 AM, Adrian Mariano via Discuss wrote: >> Jordan, BOSL2 will help you avoid that trig and decrease the required >> thinking as shown below.  :) > > Thanks, and I agree that's more obvious, but it's still unsatisfying > that it's not a sequence of 45° rotates.  It probably *can't* be such > a sequence, but it *should* be.
JB
Jordan Brown
Fri, Jan 23, 2026 1:51 AM

On 1/22/2026 2:54 PM, Adrian Mariano wrote:

Do modules get special handling of tail recursion?  

I forgot the distinction.  I don't know, probably not.

On 1/22/2026 2:54 PM, Adrian Mariano wrote: > Do modules get special handling of tail recursion?   I forgot the distinction.  I don't know, probably not.
CC
Cory Cross
Fri, Jan 23, 2026 3:03 AM

OpenSCAD turns all your input into primitive shapes (circle, cylinder, polyhedron, etc), operations (union, intersection, and difference), and placement/resize (translate, rotate, scale, etc get turned into multmatrix). It doesn't try to be very smart about this and optimize (at this stage, at least); IIRC translate wrapping a translate results in two nested multmatrix operations, when that could obviously be one (if nothing was using the intermediate stage).

But notice I didn't list modules nor loops. Every module instantiation must result in the full tree of primitives, operations, and matrix operations because those are the only things the intermediate form can represent. It can't even do math; every value must be a literal number. It's simply impossible to write a subtree and reuse it. Thus it is impossible to have tail call elimination because you can't even represent calls!

  • Cory

On January 22, 2026 4:07:09 PM PST, Adrian Mariano via Discuss discuss@lists.openscad.org wrote:

The last statement in drawpt is an if() statement, not a recursion.  But I
suspect that modules don't give special handling to tail recursion, even if
more generously interpreted.  I think it's not something that people
normally try to do---thousands deep recursion in a module.  My application
here is rather weird and there's probably a better way to approach the
problem of exploring the group generated by 45 deg rotations.  I just took
a quick/lazy one, figuring that if there was some structure it might pop
out.  It could be rewritten as a function that computes all the points.
That would get tail recursion, and then you could run arbitrarily many
points.  And you could check how close the best match is to [1,1,1].  But
for the picture, looping drawpt() isn't an inferior choice, in terms of
quality of the result.

On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

Evidently not, as drawpt is eligible for tail recursion as written.
On 1/22/26 15:15, 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 turns all your input into primitive shapes (circle, cylinder, polyhedron, etc), operations (union, intersection, and difference), and placement/resize (translate, rotate, scale, etc get turned into multmatrix). It doesn't try to be very smart about this and optimize (at this stage, at least); IIRC translate wrapping a translate results in two nested multmatrix operations, when that could obviously be one (if nothing was using the intermediate stage). But notice I didn't list modules nor loops. Every module instantiation must result in the full tree of primitives, operations, and matrix operations because those are the only things the intermediate form can represent. It can't even do math; every value must be a literal number. It's simply impossible to write a subtree and reuse it. Thus it is impossible to have tail call elimination because you can't even represent calls! - Cory On January 22, 2026 4:07:09 PM PST, Adrian Mariano via Discuss <discuss@lists.openscad.org> wrote: >The last statement in drawpt is an if() statement, not a recursion. But I >suspect that modules don't give special handling to tail recursion, even if >more generously interpreted. I think it's not something that people >normally try to do---thousands deep recursion in a module. My application >here is rather weird and there's probably a better way to approach the >problem of exploring the group generated by 45 deg rotations. I just took >a quick/lazy one, figuring that if there was some structure it might pop >out. It could be rewritten as a function that computes all the points. >That would get tail recursion, and then you could run arbitrarily many >points. And you could check how close the best match is to [1,1,1]. But >for the picture, looping drawpt() isn't an inferior choice, in terms of >quality of the result. > >On Thu, Jan 22, 2026 at 6:42 PM Curt McDowell via Discuss < >discuss@lists.openscad.org> wrote: > >> Evidently not, as drawpt is eligible for tail recursion as written. >> On 1/22/26 15:15, 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