On 14.10.19 15:07, kitwallace wrote:
Anyone able to suggest a work-around?
Could you please try with the nightly build? I believe it
should be able to do tail recursion elimination with this
code, thanks to
https://github.com/openscad/openscad/pull/3020
ciao,
Torsten.
I have a function for generating a sequence of points from an L-System
string, such as might be used to define a Dragon curve.
The function itself is tail-recursive but blows up on recursion calling
concat() - it fails with list ps length somewhere between 2k and 4k
Anyone able to suggest a work-around?
function string_to_points(s,step=1,angle=90,pos=[0,0,0],dir=0,i=0,ps=[]) =
i == len(s)
? concat([pos],ps)
: let(c=s[i])
let(newpos =
c=="F" ||c=="A" || c=="B"
? pos + step*[cos(dir), sin(dir)]
: pos)
let(newdir =
c=="+"
? dir + angle
: c=="-"
? dir - angle
: dir)
string_to_points(s,step,angle,newpos,newdir,i+1,concat([pos],ps))
;
Kit
--
Sent from: http://forum.openscad.org/
On, 14.10.2019, 13:59, kitwallace kit.wallace@gmail.com wrote:
Anyone able to suggest a work-around?
With the let() clauses of your code, no tail recursion elimination will be
done by older OpenSCAD versions.
An alternative to Torsten Paul's suggestion is to eliminate the let()
clauses from your code.
Something like:
function string_to_points(s,step=1,angle=90,pos=[0,0,0],dir=0,i=0,ps=[]) =
i == len(s)
? concat([pos],ps)
: string_to_points(s,
step,
angle,
s[i]=="F" ||s[i]=="A" || s[i]=="B" // newpos
? pos + step*[cos(dir), sin(dir)]
: pos,
s[i]=="+" // newdir
? dir + angle
: s[i]=="-"
? dir - angle
: dir,
i+1,
concat([pos],ps) )
;
I haven't tested this code.
Ronaldo, sadly, that code throws the same error on version 2019-05
Torsten, I'm not quite up with using the nighlies but great to see that tail
recursion is now handling this case - I will wait for the next development
snapshot - I could supply the code as a test case if its of interest
Kit
--
Sent from: http://forum.openscad.org/
Ronaldo, sadly, that code throws the same error on version 2019-05
That is surprising! Anyway, as another alternative, you may express your
function iteractively instead:
function points_from_string(s,step=1,angle=90,pos=[0,0,0],dir=0) =
[for( i = 0,
ps = [pos];
i <= len(s);
c = s[i],
pos = c=="F" ||c=="A" || c=="B"
? pos + step*[cos(dir), sin(dir)]
: pos,
dir = c=="+"
? dir + angle
: c=="-"
? dir - angle
: dir,
ps = concat([pos], ps),
i = i+1 )
if(i==len(s)) each ps ];
s = "FA+BA-FB";
echo(string_to_points(s));
echo(points_from_string(s));
Just to make things a bit less mysterious, the reason why 2019.05 and before
don't do tail recursion in Ronaldo's recursive example, is that the old
implementation requires exactly one branch of the ternary to be a function
call. But both branches are function calls: "concat" and "string_to_points".
A hack-around can be to replace "? concat([pos],ps)" with "? assert(true)
concat([pos],ps)", or something similarly silly (and note that the "assert"
function is not present in the 2015 versions). Iteratively is probably the
way to go here :)
--
Sent from: http://forum.openscad.org/
Well blow me! I've never seen that iterative style before. Certainly a viable
workaround -although I feel a bit - you know - dirty :)
http://forum.openscad.org/file/t229/dragon-13.jpg
Dragon curve after 13 iterations
Actually my original code was flawed because it added duplicate points but
easily fixed.
L-system code with examples is here
https://github.com/KitWallace/openscad/blob/master/tiling/lsystem.scad
Thanks guys
Kit
--
Sent from: http://forum.openscad.org/
On 15.10.19 02:34, adrianv wrote:
That is interesting. So by putting the variables inside
the for loop it is possible to update variable values with
dependency on the last iteration?
No, each iteration has a new variable scope just as with
recursion. See the manual for what the recursive call
looks like.
I compared run time performance and the run time of the
iterative solution is not faster than the tail recursive
one (using the "assert" hack). That's sort of disappointing.
How could it be faster? The resulting evaluation is exactly
the same.
ciao,
Torsten.
That is interesting. So by putting the variables inside the for loop it is
possible to update variable values with dependency on the last iteration?
I compared run time performance and the run time of the iterative solution
is not faster than the tail recursive one (using the "assert" hack).
That's sort of disappointing.
--
Sent from: http://forum.openscad.org/
On 14.10.19 16:55, kitwallace wrote:
Torsten, I'm not quite up with using the nighlies but> great to see that tail recursion is now handling this
case - I will wait for the next development snapshot
I could supply the code as a test case if its of interest
Yes, that would be nice. I suspect that code did not get
much real world testing so far, so throwing some bigger
examples at it would be interesting.
ciao,
Torsten.