[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(4)
Thanks, Gabriele, I have enjoyed studying this foreach code you created! Excellent! I appreciate your help, it's very valuable. I wanted to say, sorry for not getting back to you immediately, there's a lot going on right now!!! Ciao! -Galt p.s. The way you use bind on this-context is something new to me, it seems, I am enjoying this kind of enlightenment. >= Original Message From [EMAIL PROTECTED] = >Hello [EMAIL PROTECTED]! > >On 28-Ago-00, you wrote: > > g> By the way, do you know how Rebol itself > g> does foreach internally? Do they use a function > g> like you did, or is it done some other way? > >Probably they're doing something like: > > foreach: func [ >"Evaluates a block for each value(s) in a series." >'word [get-word! word! block!] {Word or block of words to set each time (will be local)} >data [series!] "The series to traverse" >body [block!] "Block to evaluate each time" >/local amount > ] [ >if get-word? word [word: get word] >use compose [(word) this-context] [ ; of course the native code >; doesn't need the extra word > bind body 'this-context > amount: either block? word [length? word] [1] > while [not tail? data] [ >set word data >do body >data: skip data amount > ] >] > ] > >Obviously the native code might look a lot different. ;-) > >Also, since they're probably not calling the WHILE native, there >will be some magic code to make BREAK etc. work as expected. > >Regards, >Gabriele. >-- >Gabriele Santilli <[EMAIL PROTECTED]> - Amigan - REBOL programmer >Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(4)
The original question, which may have been posted by Paul Tretter, but I don't remember exactly, was something like this: a: "101" foreach item a [ print index? item ] Now, we all know why that doesn't work. This does, but probably doesn't really address his concern: forall a [ print index? a ] and now you have to remember to reset a a: head a and you have to use "first a" to get the element everywhere in your code. Sometimes I myself have wished I could have my cake and eat it too. I want the index that forall gives and I want the ease of use of the assigned word for each element. I am pretty dang sure lots of other Rebolers out there beside me have come across the same thing. So I wrote something that did that, but I couldn't figure out how to do that simply. Gabriele came up with a wonderful little gem and Ladislav and he made some more little improvements. So, here it is, a kind of foreach with index access: ideal-looper: func [ 'element [word!] 'index [word!] series [series!] code [block!] /local f i ] [ f: func reduce [[throw] element [any-type!] index] code i: 1 while [i <= length? series] [f series/:i i i: i + 1] ] >Regards, >Gabriele. And that's why we love Rebol! And the punchline for Paul would be this usage: a: "101" ideal-looper item indx a [ print [item indx] ] the output is: 1 1 0 2 1 3 == false And of course, there is no harm in having calls to "ideal-looper" multiply nested or used inside recursively called functions. And the words used for the element and index are also just known in the "scope" of the code block, and will not stomp on your global wordspace. I still don't really understand Ladislav's addition of Throw and [any-type!]. Would anyone care to divulge? -Galt
[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(4)
Hi, being asked I try to explain my changes. 1. Thanks, Gabriele, I forgot to use one more Throw, but the original is needed too. I used Throw attribute to make sure, that any Return or Exit contained in code like: f: does [ideal-looper elem indx [1 2 3] [exit]] does what it should, ie. causes the exit of F. 2. Any-type! specification is needed, because a series in Rebol can contain even eg. Unset! values, in which case the function without the spec. wouldn't work. 3. For uses While anyway, so it is a shortcut. (see Source For, but look out! It still contains the series bug I reported to feedback.) The corrected version: ideal-looper: func [ [throw] 'element [word!] 'index [word!] series [series!] code [block!] /local f i ] [ f: func reduce [[throw] element [any-type!] index] code i: 1 while [i <= length? series] [f series/:i i i: i + 1] ] Regards Ladislav > Hello [EMAIL PROTECTED]! > > On 27-Ago-00, you wrote: > > l> Hi, > > l> just a small change: > [...] > > Perhaps you meant: > > ideal-looper: func [ > 'element [word!] > 'index [word!] > series [series!] > code [block!] > /local f i > ] [ > f: func reduce [[throw] element [any-type!] index] code > i: 1 > while [i <= length? series] [f series/:i i i: i + 1] > ] > > F is the function that should have the THROW attribute. > > Regards, > Gabriele. > -- > Gabriele Santilli <[EMAIL PROTECTED]> - Amigan - REBOL programmer > Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/ > >