Hi Joel,
if I understood what you were after, you wanted to have:
probe reduce probe repeat i 5 [append [] use [.i] [.i: i '.i]]
Coffee
Ladislav
----- Original Message -----
From: Joel Neely <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, October 10, 2001 2:39 PM
Subject: [REBOL] Fun with blocks of words (a tad longish)
> Hello, all,
>
> I found the following little explorations instructive while thinking
> about words and contexts. I hope they are of interest/value to
> someone else.
>
>
> Let's make a block of words:
>
> >> bow: []
> == []
> >> repeat i 5 [append bow i]
> == [1 2 3 4 5]
>
> Woops! That gave me a block of integers, not a block of words.
> Besides which, I hate using variables unless necessary.
>
> I can get rid of the variable BOW (since REBOL is a very literal
> language) like this:
>
> >> repeat i 5 [append [] i]
> == [1 2 3 4 5]
>
> Now let's get a block of words instead of a block of integers:
>
> >> repeat i 5 [append [] [i]]
> == [i i i i i]
>
> But is that a block of five homographs (distinct words whose names
> are all spelled the same), or is it a block with five references
> to the same word?
>
> >> reduce repeat i 5 [append [] [i]]
> == [6 6 6 6 6]
>
> It's five references to the same word.
>
>
> Thought 1: REPEAT creates a context when executed.
> Within the block that is evaluated REPEATedly,
> the word that is the first argument to REPEAT is in that
> new context. (* Not considering the use of nested words
> that also create contexts, e.g. USE, etc...)
>
>
> But what if I *really* want a block of homographs? Hmmmm.
> Let's try sticking another context-creating word in there.
>
> >> reduce repeat i 5 [use [.i] [.i: i append [] [.i]]]
> == [5 5 5 5 5]
>
> Again we get five references to the same word!
>
>
> Thought 2: USE creates a context when executed. When
> word(s) in the first argument appear in the
> second argument, they are words in that context. It
> appears that there's a side-effect of "remembering" that
> fact so that subsequent USEs of the same block are still
> involved with that context.
>
>
> Hmmm. If I give USE a fresh second block every time, then I can
> avoid the side-effect.
>
> >> reduce repeat i 5 [use [.i] copy [.i: i append [] [.i]]]
> == [5 5 5 5 5]
>
> Duh! A simple COPY doesn't get to the .I that's in an additional
> "layer" of block nesting.
>
> >> reduce repeat i 5 [use [.i] copy/deep [.i: i append [] [.i]]]
> == [5]
>
> Double-duh! Now there's a fresh empty block for every evaluation
> of USE. Sigh... The only way I can think of to get around that is
> to re-introduce a word to serve as a "variable".
>
> >> b: []
> == []
> >> reduce repeat i 5 [use [.i] copy/deep [.i: i append b [.i]]]
> == [1 2 3 4 5]
>
> Aha! It looks like I (finally!) have five homographs! I'd really
> like to look at them, though...
>
> >> repeat i 5 [use [.i] copy/deep [.i: i append b [.i]]]
> == [.i .i .i .i .i .i .i .i .i .i]
>
> Rats! That's why I hate using "variables". Side-effects accumulate!
> While I'm at it, I'll keep the result this time so that I can look
> at the "raw" block and also REDUCE it:
>
> >> b: []
> == []
> >> c: repeat i 5 [use [.i] copy/deep [.i: i append b [.i]]]
> == [.i .i .i .i .i]
> >> reduce c
> == [1 2 3 4 5]
>
> Yes! Five homographs! Just what I wanted!
>
>
> Thought 3: COPY/DEEP is a way to avoid the side-effect
> that USE has on its second block. However,
> I have to remember that COPY/DEEP also blows away any
> side-effects on literal values!
>
>
> I wonder -- is there any way to get homographs without losing the
> ability to have literal values? How else can we create contexts?
> How about with a function?
>
> >> apparg: func [b x] [append b [x]]
> >> c: repeat i 5 [apparg [] i]
> == [x x x x x]
> >> reduce c
> == [5 5 5 5 5]
>
> Hmmmph! (Insert appropriate numbers of "duh" ;-) I'm back to
> getting five occurrences of the same word. Oh yeah...
>
>
> Thought 4: The context of a function is persistent.
> Subsequent uses of the function are using
> the same context. This isn't like ___ (insert name of
> commonly-used language here) which creates a new frame
> or environment for each invocation of a function.
>
>
> I suspect that this might be a performance choice. Create the
> context when the function is defined, and keep it around to avoid
> repeating that work every time the function is evaluated.
>
> Errrk? What about recursion?
>
> >> rapparg: func [b i x] [
> [ either i > x [b] [rapparg append b [i] i + 1 x]
> [ ]
> >> c: rapparg [] 1 5
> == [i i i i i]
> >> reduce c
> == [1 1 1 1 1]
>
>
> Well, it *looks like* I is getting saved and restored for the
> recursive calls, but let's make sure (by using some fairly
> gnarly-looking before-and-after tracing):
>
> >> rapparg: func [b i x /local r] [
> [ print b
> [ r: either i > x [b] [rapparg append b [i] i + 1 x]
> [ print r
> [ r
> [ ]
> >> c: rapparg [] 1 5
>
> 2
> 3 3
> 4 4 4
> 5 5 5 5
> 6 6 6 6 6
> 6 6 6 6 6
> 5 5 5 5 5
> 4 4 4 4 4
> 3 3 3 3 3
> 2 2 2 2 2
> 1 1 1 1 1
> == [i i i i i]
> >> reduce c
> == [1 1 1 1 1]
>
> Yup! The argument block is accumulating a bunch of references
> to the same word (an argument) whose value is being saved and
> restored to make the recursive call behave like one would
> expect it to.
>
>
> Thought 5: I suspect that means that there's a time
> penalty for using recursion (compared to
> repeatedly calling the same function within an iteration)
> but that benchmark will have to wait for another day.
>
>
> Wait a minute! My attention is wandering! I wanted to make a
> block of homographs. How else can I make new contexts? Whoa!
> I can make a new function everytime I iterate!
>
> >> c: repeat i 5 [do func [b x] [append b [x]] [] i]
> == [x x x x x]
> >> reduce c
> == [1 2 3 4 5]
>
> Yeehah! Now I get a fresh context (and therefore a fresh word)
> every time.
>
>
> Thought 6: FUNC appears *not* to have the side-effect
> of altering its second block (in the way
> that USE does). Subsequent uses of FUNC ... ... really
> get me a new context for each evaluation.
>
>
> Of course, being stubborn as well as simple-minded, I can't help
> but think about the idea of USE inside the body of a function.
> Since USE seems to have a side-effect on its second (literal)
> argument, I would expect to get the same word over and over.
> Let's try it...
>
> >> appuse: func [b x] [use [.x] [.x: x append b [.x]]]
> >> c: repeat i 5 [appuse [] i]
> == [.x .x .x .x .x]
> >> reduce c
> == [1 2 3 4 5]
>
> Wot??? I got five homographs! Does USE inside a function body
> behave differently than USE at the console level?
>
> >> repfun: func [b x] [repeat i x [use [.x] [.x: i append b [.x]]]]
> >> c: repfun [] 5
> == [.x .x .x .x .x]
> >> reduce c
> == [1 2 3 4 5]
>
> It does! We're back to five homographs, even though the body of REPFUN
> is essentially the same as the unsucessful attempt from the console
> prompt earlier (except for using an argument instead of a literal as
> the object of the APPEND).
>
>
> Thought 7: There's more going on here than meets the eye.
> I need another cup of coffee.
>
>
> As usual, feedback/comments/corrections/coffee are welcome! ;-)
>
> -jn-
>
> --
> joelDOTneelyATfedexDOTcom
> --
> To unsubscribe from this list, please send an email to
> [EMAIL PROTECTED] with "unsubscribe" in the
> subject, without the quotes.
>
>
--
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the
subject, without the quotes.