[REBOL] Re: Contexts of contrived blocks
From: lmecir:mbox:vol:cz at: 9-May-2001 22:35
Hi Joel,
you wrote:
> Well, as the old gentleman said, "I don't know the answer,
> but I surely do admire the question!"
>
> This seems like it might be related to another small mystery
> I've been pondering on recently. Given the code:
>
> 8<------------------------------------------------------------
> #!/usr/local/bin/rebol
>
> rebol []
>
> make object! [
> scoper: func [
> argvar [integer!] recur? [logic!] /local locvar
> ][
> locvar: argvar + 1
> use [usevar] [
> usevar: argvar + 2
> print [argvar recur? locvar usevar]
> if recur? [scoper argvar + 10 false]
> print [argvar recur? locvar usevar]
> ]
> ]
> scoper 1 true
> ]
> 8<------------------------------------------------------------
>
> we get the following behavior:
>
> 8<------------------------------------------------------------
> >> do %scoper.r
> 1 true 2 3
> 11 false 12 13
> 11 false 12 13
> 1 true 2 13
> >>
> 8<------------------------------------------------------------
>
> Now, it's clear (in some sense) *WHAT* is happening. The USE
> establishes a separate context in which USEVAR is known. The
> single instance of that context persists across the recursive
> call, therefore the value to which USEVAR is set in the inner
> call is still acessible upon return to the outer call.
>
> What is not clear to me is *HOW* and *WHEN* that takes place.
> Does the USE establish that context...
>
> 1) when the source file is loaded?
> 2) when SCOPER is first invoked?
> 3) at some other time I haven't imagined?
>
> Option (1) seems inconsistent with what I think I understand
> about how FUNC and MAKE OBJECT! do (create a new context when
> executed). Option (2) leaves me wondering, "How does it know
> that the recursively nested call should re-use the context
> created in the outer call (instead of creating another one)
> and how does it find that existing context?"
>
> It still appears that contexts have much deep magic associated
> with them!
>
> -jn-
as you might have guessed, 3) is correct.
See this:
nm-use: func [
{
A non-modifying use version.
Defines words local to a block.
}
[throw]
words [block! word!] {Local word(s) to the block}
body [block!] {Block to evaluate}
] [
use words copy/deep body
]
make object! [
scoper: func [
argvar [integer!] recur? [logic!] /local locvar
][
locvar: argvar + 1
nm-use [usevar] [
usevar: argvar + 2
print [argvar recur? locvar usevar]
if recur? [scoper argvar + 10 false]
print [argvar recur? locvar usevar]
]
]
scoper 1 true
]
1 true 2 3
11 false 12 13
11 false 12 13
1 true 2 3
Regards
Ladislav