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

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

From: rebol:techscribe at: 26-Jul-2000 0:31

Hi Gabriele, you wrote:
>I'm glad to talk with you too; I hope to get your book soon, too, >so I'll be able to send you some bug report. ;^)
I've set up a mailing list on my Web server for the book (for bug fixes and clarifications and ongoing discussions). You can join the mailing list at my Website: After reading your email carefully, my impression is that our main discrepancy has to do with perspective. I view REBOL as a programming language, and I think about REBOL in terms of concepts, principles that lend themselves to describe how REBOL acts as a language. In contrast, you apparently think about REBOL as an interpreter implementation. You tend to speculate about how the REBOL interpreter is likely to implement some language feature. [snip]
>So, let's prove there's no hierarchy here: > >>> f "This is f's argument" >This is g's argument. This is f's argument This is the global word. >>> code: second :g >== [ > print [g-arg f-arg global-word] >] >>> g's-context-word: code/2/1 >== g-arg >>> print code/2 >This is g's argument. This is f's argument This is the global word. >>> print bind [g-arg f-arg global-word] g's-context-word >** Script Error: f-arg has no value. >** Where: f-arg global-word
Carl commented on a similar example you provided while binding a block to an embedded object, and declared the bind behavior you demonstrated to be a bug. He didn't clarify, and I will rely on his response (see Carl's message in this thread. Date: Mon, 24 Jul 2000 15:40:32 -0700 Subject: [REBOL] Bug in 'use? Re:(9)) with respect to this behavior as well. I conclude from Carl's comment that bind's intended behavior is to bind the block such that all words that occur in the block behave as they would, if the block had been defined in the context it is being bound to. I.e. if print [g-arg f-arg global-word] evaluated in the g function's context were to generate This is g's argument. This is f's argument. This is the global word. then print bind [g-arg f-arg global-word] g's-context-word should generate the same result. If it doesn't, then it is - in Carl's words - a bug. Hierarchic context table inheritance is REBOL's intended behavior.
>>> f-arg: "Global f-arg!" >== "Global f-arg!" >>> print bind [g-arg f-arg global-word] g's-context-word >This is g's argument. Global f-arg! This is the global word. > >So, how does it work when calling F? When F is created, a new >context table is created.
Thank you. I went to pains to demonstrate that.
>Then the BIND function is called to bind
Metaphorically speaking? I have never seen the bind function called during the construction of a function. If you source func and function, you will find that neither of these mezzanine functions call bind. They both use make function! ... and I have no access to the code that is executed when make function! is called.
>the body block to that context table (this means binding each word >in the block and the blocks (any-block!s actually) it contains, >but only if present in the context table). >So when F is created >the block: > > [ > print [g-arg f-arg global-word] > ] > >gets bound to F's context; more precisely, >the word "f-arg" gets >bound to F's context, while "print", "g-arg" and "global-word" >aren't changed (so they're still bound to the global context).
I think this is a conceptual problem. There is no g-arg defined in the global context. Accordingly "g-arg" was never bound to the global context. Therefore "g-arg" cannot "still" be bound to the global context.
>When F is executed, the function G is created, and thus the block >above gets bound to G's context. Again, only the word "g-arg" is >affected, while "print" and "global-word" are left bound to the >global context and "f-arg" to F's context.
Thank you. Note what you are saying here. You are looking at this from a different perspective, an implementation perspective, - nevertheless - you are formulating a mechanism that exactly results in context inheritance. You may dislike the term "context (table) inheritance", but I think it expresses the fact quite well that words used - but not defined - in an embedded function, are interpreted in the context of their parent function - provided they are defined in that function. Or in their immediate parent's parent function ... until the global context is reached. Your implementation view (though speculative, but reasonable) supports my conceptual representation, don't you think?
>The result is what you expect, with "f-arg" bound to F's context, >"g-arg" bound to G's context and "global-word" bound to the global >context, but this is only a (wanted) side effect of REBOL static >binding. > > r> Example 2 for Context Hierarchy: > >[...] > >The same goes here. No hierarchy needed.
No hierarchy "needed"? Did you not begin by claiming in your previous email
>Anyway, I can prove that there is no context hierarchy:
then continue by saying in this email
>So, let's prove there's no hierarchy here:
Now "No hierarchy NEEDED" has become the "same" as proving "there's no hierarchy here:"? After describing a speculative process (albeit a reasonable one) that brings about a behavior, which can be described - with precision - as a context table hierarchy, you have lowered your attack from I can prove that there is no context hierarchy to "no hierarchy needed"? Perhaps having thought through a process through which REBOL's hierarchical context behavior may be implemented, your opposition to this concept has become weaker, from proving "there's no hierarchy" to avoiding the hierarchy use of the word hierarchy, "no hierarchy needed"? Your speculation regarding the binding of words during the function's construction is only reasonable, because we know already, that the construction will eventually have to lead to a behavior that is consistent with the observable hierarchic behavior that REBOL displays, when it resolves words in embedded functions.
> r> is based on the assumption that "embedded" objects are created > r> in the context of their "parent" objects and inherit the > r> parent object's context. This is not the case - as your > >Using your reasoning above, I could prove exactly the opposite. >Look:
Here I stand corrected by Carl's email. Apparently, the behavior you demonstrate here is a bug, and not REBOL's intended behavior. Accordingly, I should say, that context table inheritance is also effective for objects, but it is not implemented correctly.
>>> a: 1 b: 1 c: 1 >== 1 >>> obj1: make object! [ >[ a: 2 >[ obj2: make object! [ >[ b: 2 >[ obj3: make object! [ >[ c: 2 >[ print [a b c] >[ ] >[ ] >[ ] >2 2 2 > >So, how did this happen? Context hierarchy for objects? I think >not. :-)
Why would this have anything to do with context hierarchies for objects? The resulting object is:
>> probe obj1
make object! [ a: 2 obj2: make object! [ b: 2 obj3: make object! [ c: 2 ] ] ] Note that print [a b c] does not occur in the object.
> r> In summary, functions are evaluated in a context hierarchy, > r> objects are not. Recall that I was discussing the behavior of > >I'm sorry, but this is wrong, as you can see above.
How does your example above prove anything with respect to context table hierarchies and objects? The expression print [a b c] is evaluated at the time the objects are being constructed and does not survive the construction process. Therefore the construction process of objects determines the context in which print [a b c] is evaluated, and not the context of the resulting objects.
>There's >absolutely no difference between a function's context and an >object's context.
Actually there is! Observe:
>> obj1: make object! [
[ a: 1 [ obj2: make object! [ [ b: a + 1 [ f: func [x] [ print a + x ] [ ] [ ]
>> obj1/obj2/b
== 2
>> obj1/obj2/f 1
>> obj1/a: 100
== 100
>> obj1/obj2/b
== 2
>> obj1/obj2/f 1
> r> Perhaps my mental model of context tables and the context > r> table hierarchy, multiple context tables that are effective > r> during recursive function calls, and the stack in which the > r> context tables that are currently defined for a function are > r> stored, while it is recursively being evaluated, is a good > r> model to understand recursive function calls? > >It is accurate enough,
Thank you!
>except for the hierarchy.
This objection should by now be layed to rest! It's a bug.
>The only point >against a stack of contexts instead of a stack of values is that >that would require a new binding of the function body for each >recursion, >which I think it's unlikely.
You think it's "unlikely", because you are speculating about how things are IMPLEMENTED in the REBOL interpreter. This is not my issue. I'm not trying to outguess the REBOL interpreter architecture. My only concern is in finding a useful representation for how the language works. And with respect to that, I think that it does not make a difference if the interpreter indeed saves and stores context tables and does/or does not bind its body at each recursion. Pushing and popping context tables could be as cheap and pushing and popping a context pointer that is declared as: struct CONTEXT_TABLE { char * words []; void * values []; } * context;
>Of course, if you think in >terms of dinamic binding this makes no sense, so we should find an >an agreement on that first. :)
Since you raise this as an issue, go ahead ;-).
> r>> Ladislav suggested that only tha values are remembered, while > r>> the context table is reused. So the function has still only > r>> one context table in any time, but keeps a stack of values. > > r> Gabriele, it's obvious that more things are being remembered > r> than just values! > > r> 1. The association of words with values is being remembered! > r> 2. The fact that the association of these words with these > r> values is effective for this particular function is being > r> remembered. > >Remembering the values and their order is enough; anyway, what I'm >saying is that the same context table is reused, but its contents >are saved and then restored. Again, this would make no sense if >REBOL did the word lookup at runtime, but it doesn't --- it does >the lookup at bind time.
it does the lookup at bind time. I'm not sure what you mean by that.
>Hmm... let's rewind time a bit, and let's run REBOL 2.0: > >REBOL >Copyright (C) 1998-1999 REBOL Technologies >REBOL is a Trademark of REBOL Technologies >All rights reserved. > >loading... >Finger protocol loaded >Daytime protocol loaded >SMTP protocol loaded >POP protocol loaded >HTTP protocol loaded >FTP protocol loaded >Script: "REBOL Extended Definitions" (22-May-1999/0:10:40) >Script: "User Preferences" (15-May-1999/12:58:54) >>> obj: make object! [x: 1] >>> word: in obj 'x >== x >>> get word >== 1 >>> probe obj > >make object! [ > x: 1 >] >>> first obj >== [self x] >>> change next first obj 'a >== [] >>> probe obj > >make object! [ > a: 1 >] >>> get word >== 1 >>> word >== x > >So, how is that?
The context was extended. That explains how x remains bound to 1.
> r>> Only the value column is stored in a stack and reinitialized, > r>> as happens when the function is called the first time. > > r> Ths is an implementation issue and does not touch on the > >I agree here. But we're speculating about the implementation, >aren't we? :-)
No. I'm providing a fragment for a conceptual understanding of REBOL.
>(P.S.: if you reply to this message, but don't get a reply from >me, it's probably because I didn't get you message. I got only 6 >messages from the list today. I still ahve to figure out why and >where I'm losing messages; in the meantime, if you want you can >resend your replys to me directly if you don't see answers from me >in the list.)
I'm cc'ing you the message, just in case ... :-). ;- Elan [ : - ) ] author of REBOL: THE OFFICIAL GUIDE REBOL Press: The Official Source for REBOL Books visit me at