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

[REBOL] Bug in 'use? Re:(2)

From: rebol:techscribe at: 23-Jul-2000 15:49

Hi Eric, you wrote:
>I think it's needlessly complex to say that the g function "has access >to f-arg".
That is complex?
>It's much simpler to say that the word 'f-arg is bound to the >context of the function F,
That's "much simpler to say"? ;-). Perhaps. It does not say, however, if 'g has access to the f-arg that is defined in the context of the 'f function.
>and that the function G has no privileged access >to that binding of 'f-arg by being within some kind of hierarchy.
But the embedded function g (a function that is defined in the context of function f) *does* have privileged access to words local to the context of function f. That happens to be an empirical fact. The questionable *simplicity* of saying that function 'g "has no privileged access to that binding" does not help, since your statement is incorrect. A simple incorrect statement is not better than a correct one. Observe:
>> x: "This is global x." >> f: func [x] [
[ g: func [] [ [ print x [ ] [ ]
>> f "this is f's argument x" >> h: func [] [ print x ] >> h
This is global x.
>> g
this is f's argument x Why does the function associated with 'g (I'll call it the 'g function) report f's argument, and not the global 'x, as 'h does? It's because the 'g function, which is defined in f's context, inherits f's context table. Therefore the 'x it prints is the 'x bound in f's context, not the global context. The term "f's context table" is simply a shortcut for saying" "all word/value pairs defined in the context of the 'f function". Inheritance means that - without any programmatic efforts - REBOL automatically exposes f's context table to the g function, because the g function is embedded in f's context. Even though 'x is defined globally, the 'x binding effective for 'g is x's binding in 'f, because 'g is defined in 'f. (Mind you, I am not talking about the set-word g: being defined in 'f, I am talking about the function itself, the value 'g is associated with, being defined in 'f. Nor am I talking about 'f. I'm using 'f as a short way of saying "the function associated with f".) This inheritance is hierarchical. Observe:
>> x: "This is global x." >> y: "This is global y." >> z: "This is global z." >> f: func [y z] [
[ g: func [z] [ [ print ["g's x" x] [ print ["g's y" y] [ print ["g's z" z] [ ] [ print ["f's x" x] [ print ["f's y" y] [ print ["f's z" z] [ g "z argument passed to g." [ ]
>> >> f "The y argument passed to f." "The z argument passed to f."
f's x This is global x. f's y The y argument passed to f. f's z The z argument passed to f. g's x This is global x. g's y The y argument passed to f. g's z z argument passed to g. Both 'f and 'g inherited the global context table, see the value reported for 'x. The 'f function uses the values of its local context table for the words 'y and 'z. The 'g function inherits the global context table for 'x, inherits f's private context table for 'y and uses its own context table for 'z. I think this inheritance behavior is expressed fairly well with the word hierarchical inheritance . There is a hierarchy of context tables. REBOL constructs this hierarchy top-to-bottom, from the higher-level function down to the lower-level function defined in the higher-level function's context. REBOL consults with context tables in the hierarchy bottom-up when it resolves words and looks up what the value they are bound to, beginning with the context table for the lower-level function, and, if it can't find the word's definition there, it searches in the next-higher context table, and so on, until it arrives at the global context table.
>(The binding of 'f-arg of course took place even before the function G >was created.)
Of course. Who was disputing that? I'm describing how g gets to access the 'f' functions f-arg, not when f-arg is bound to the f' function. Two different things.
>Here's proof, I think: > >>> f: func[x y][x + y] >>> g: func[x y][x + y] >>> f 1 2 >== 3 >>> g 5 6 >== 11 >>> b: copy second :f >== [x + y] >>> c: copy second :g >== [x + y] >>> append clear second :f c >== [x + y] >>> append clear second :g b >== [x + y] >>> f 1 2 >== 11 >>> g 5 6 >== 3 >>> f 10 11 >== 11 >>> g 5 6 >== 21 > >Here I've rebuilt the code for F and G, and now their bodies contain words >'x and 'y bound within each other's contexts. I think it's simplest to say >that those words "know" where they are bound. >When you call F, it sets >the values of all instances of 'x and 'y bound to its context, but in this >case all those instances are now in the body of G, not within F's own >body. F doesn't see the word 'x within its body, and look up the value of >'x in some table, it just uses the value that results when 'x is evaluated. >
Nice. I was talking about something else, something your proof does not address. I was talking about rules that guide REBOL when it defines in which context a word is bound in ambiguous situations. What's ambiguous about the situation? Given: x: "Global x." y: "Global y." f: func [x] [ g: [x y] [ print ["In g:" x y] h: [y] [ print ["In h:" x y] ] h "Evaluting h with argument y." ] g "Evaluating g with argument x." "Evaluating g with argument y." ] A Confused 'x ============= Why is this situation ambiguous? Because staring real hard at 'x in the statement print ["In h:" x y] does not reveal if this 'x is the one that knows that it is bound globally, or if this 'x is the one that "knows" that it is bound in the 'f function, or if it is the 'x bound in the 'g function. All this poor 'x for sure "knows" is that it is not bound in the context of the 'h function, because there is no 'x defined local to the 'h function. 'x suffers an identity crisis. There are, however, observable rules that define what this 'x "knows". My intention was to express these observable rules with three simple terms: context table , "inheritance", and "hierarchy". The 'x in the statement print ["In h:" x y] is the 'x bound in the 'g function, because the 'h function is defined in g's context. Therefore the 'h function inherits g's context table, as well as f's context table and the global context table. Since words are resolved bottom-up, and the lowest-level context table inherited by the 'h function is the 'g function's context table, this 'x is bound in 'g. Recursive Function Evaluation And Stacks ========================================= To desribe REBOL's behavior with respect to recursive function evaluations (i.e. when a function evaluates itself recursively) add a fourth term: stack . A function's context table is pushed on a stack whenever a function evaluates itself recursively. The context table is popped from the stack when a function returns from a lower recursion level to a higher recursion level. (For a more detailed account of this, see my response to Ladislav's "bug in 'use?".) Your "proof" does not touch on any of this. If it did, would it become a little more complex? ;- Elan [ : - ) ]