tailfunc
[1/8] from: rotenca::telvia::it at: 21-Nov-2001 1:49
Hi, Ladislav
can you explain to me why you use the external function Exec in your
tail-func?
Why can't you use a simple Do?
---
Ciao
Romano
[2/8] from: lmecir:mbox:vol:cz at: 21-Nov-2001 8:30
Hi Romano,
<<Romano>>
(...)
can you explain to me why you use the external function Exec in your
tail-func?
Why can't you use a simple Do?
---
Ciao
Romano
<</Romano>>
Do wouldn't handle Return in the same way as Exec does:
exec: func [body] [do body]
body: [return 1]
exec body ; == 1
do body
** Throw Error: Return or exit not in function
** Near: return 1
Cheers
Ladislav
[3/8] from: rotenca:telvia:it at: 21-Nov-2001 15:47
Hi, Ladislav
And why not an in-line function like:
compose...
do (func [] reduce [body])
I have others little questions on your code:
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
2) You leave 'result global, why?
---
Ciao
Romano
[4/8] from: lmecir:mbox:vol:cz at: 21-Nov-2001 16:41
Hi Romano,
<<Romano>>
And why not an in-line function like:
compose...
do (func [] reduce [body])
<</Romano>>
Your suggestion doesn't seem to work (?) ...
<<Romano>>
I have others little questions on your code:
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.
If we want to use logic! values, we have to use two variables, e.g. like:
loop: none
...
either loop [
finish: none
] [
until [
finish: true
error? set/any 'result exec (reduce [body])
finish
]
loop: none
...
<<Romano>>
2) You leave 'result global, why?
---
Ciao
Romano
<</Romano>>
Not only 'result, I left even the 'locals word global! It is a bug, I will
repair it and include to %Highfun.r Thanks for your feedback.
Cheers
Ladislav
[5/8] 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
<<quoted lines omitted: 16>>
> 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]
]
]
]
[6/8] from: lmecir:mbox:vol:cz at: 21-Nov-2001 20:37
Hi Romano,
It really doesn't work. See this:
f: tail-func [first second] [
print [first second]
either second = 1 [first] [
f 1 - first second - 1
]
]
f 1 400
The set-word skip is in accordance with the way how Help (from RT) is
written, that is all (future compatibility?).
I posted the newest version of http://www.sweb.cz/LMecir/highfun.r to the
web and to my Rebsite. Changes:
Tail-func included (I used a modified inline function idea as Romano
suggested).
Refined corrected (a similar bug as in Apply implementation), moreover
Refined had a "keyword" bug, which is now corrected too (a totally new kind
of trick, probably the most general one), Apply implementation changed a
bit.
Cheers
Ladislav
<<Romano>>
(...)
It works for me. Try the modified version at the end of this message.
(...)
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]
]
]
]
<</Romano>>
[7/8] from: rotenca:telvia:it at: 22-Nov-2001 0:32
Hi Ladislav,
> It really doesn't work. See this:
> f: tail-func [first second] [
<<quoted lines omitted: 4>>
> ]
> f 1 400
I didn't work (i think) because I inverted true and false: here it is the
working version, i changed the name of loop in stop to reflect new meaning and
to save a 'not or two:
stop: false
...
either stop [
stop: false
] [
until [
stop: true
error? set/any 'result do (does body)
stop
]
stop: false
return get/any 'result
]
> The set-word skip is in accordance with the way how Help (from RT) is
> written, that is all (future compatibility?).
You forget it in highfun.r.
---
Ciao
Romano
[8/8] from: lmecir:mbox:vol:cz at: 22-Nov-2001 1:29
Hi,
<<Romano>>
(...)
i changed the name of loop in stop to reflect new meaning and
to save a 'not or two:
stop: false
...
either stop [
stop: false
] [
until [
stop: true
error? set/any 'result do (does body)
stop
]
stop: false
return get/any 'result
]
<</Romano>>
indeed, I was wrong. Actually, instead of
... 'result do (does body)
a shorter
...'result (does body)
works too. It looks that I finally accepted all your suggestions.
Thanks.
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted