Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

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