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

[REBOL] Bug in 'use? Re:

From: kgd03011:nifty:ne:jp at: 24-Jul-2000 12:44

Hi Elan, I think you're going to be really busy refuting Ladislav, so I'll keep my comments brief. You wrote:
>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.
Your explanation agrees with your example, but I don't think it's quite the best one. I think the best explanation (which I'm mostly basing on what Gabriele and others have said) is: Before the function G is constructed, its body block, [print x] is already bound to the context of the function F. Of the two words in this block, 'x is defined in the "context table" of F. So when G is constructed, this block is bound to G's context, but since 'x is not redefined in that context it simply retains its binding. You could say that G inherits the binding of 'x, but I don't see any proof that G inherits f's context table . I think your explanation about embedded functions inheriting context tables has the potential of causing major confusion. My previous example was a lousy one, but here's an example involving embedded functions that can easily occur:
>> b: [print x + y]
== [print x + y]
>> f: func[x][g: func[y] b print x] >> x: 100
== 100
>> f 10
>> g 1
101 If you think in terms of "inheriting context tables", wouldn't you expect G to print 11? That's certainly what I would think. What happens here accords with my explanation, though. When G is constructed, in its body block 'x hasn't been bound to the context of F, and that binding doesn't change - it's still bound to the global context. This happens because the body block wasn't actually in the block that was bound to F's context - only the word 'b referring to the body block was. (Actually, the bindings in the original B are unchanged, since a copy is used to construct G.)
>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.
When is it that "REBOL consults with context tables"? At run time? When the function is constructed? Surely it's the latter. I think a simpler explanation than hierarchical inheritance is that when a function is constructed, it simply binds all the words in its body block that are defined in its own context (that is, its own arguments and local variables), and retains the binding of all other words. If one of the words in its body block happens to be bound to the context of another function, that word will retain its binding, whether or not one function is embedded in another one. Ladislav's tools for examining binding are very interesting. I'd just like to extract and adapt the crucial part of his argument that proves that contexts are not inherited:
>> x: y: z: 0
== 0
>> f: func[x z][g: func[y] [print [x y z]]] >> f 10 30 >> g 20
10 20 30
>> b: reduce [
[ bind 'x probe second second second :g [ bind 'x probe third second second :g] y z == [x x]
>> reduce b
== [0 10] This shows that the word 'x is nowhere in G's context table. The word 'y which _is_ in G's context does not allow us to access any bindings for 'x except the global one. The word 'z which is in F's context table _does_ allow us to access F's binding for 'x. Wish I'd thought of that! See you, Eric