[REBOL] Re: tailfunc
From: rotenca:telvia:it at: 21-Nov-2001 18:04
Hi Ladislav
> do (func [] reduce [body])
>
> <</Romano>>
>
> Your suggestion doesn't seem to work (?) ...
It works for me. Try the modified version at the end of this message.
> 1) A little thing: couldn't loop start to none?
>
> loop: none
> ...
> either loop [
> loop: 1
> ] [
> until [
> loop: none
> error? set/any 'result do (func [] reduce [body])
> not loop
> ]
> loop: none
>
> <</Romano>>
>
> Loop surely can start with the None value. But even then for the function to
> work, we have to be able to detect three different states:
>
> 1) the first one is a fresh start, signaling that the loop must be started.
>
> 2) the second one is a situation, when the loop is "running" and a recursive
> call was detected. The loop must continue.
>
> 3) the third one is a situation, when the loop is "running" and a recursive
> call hasn't been detected. The loop must finish.
I do not see any diffference between 1 and 2. What you want inizialize?
Again: try the modified version at the end of this message.
I have another little question (the last, don't worry):
Why you skip set-word!, set-word are not permitted in spec of func so the
creation of code naturally fail when you go and create the final function.
ciao
Romano
---------- modified version ------------
tail-func: function [
{Transparently creates a tail-recursive function.}
[catch]
spec [block!] body [block!]
] [
ic icb i item locals
] [
use [new-locals loop result] [
loop: false
locals: copy []
icb: copy []
i: 1
parse spec [
any [
set item any-word! (
append locals to word! :item
append icb compose [
error? set/any pick new-locals (i) get/any pick locals (i)
]
i: i + 1
) | skip
]
]
set [new-locals body] use locals copy/deep reduce [
reduce [locals body]
]
append icb compose/deep [
either loop [
loop: true
] [
until [
loop: false
error? set/any 'result do (func [] reduce [body])
not loop
]
loop: false
return get/any 'result
]
]
ic: func [
{do body with locals in new context}
[throw]
locals
] icb
throw-on-error [
func spec reduce [:ic locals]
]
]
]