Bug in 'use? Re:(9)
[1/22] from: rebol::techscribe::com at: 23-Jul-2000 0:49
Hi Gabriele,
good to hear from you.
> r>> From the point of a statement that is being evaluated, there
> r>> exists a
<<quoted lines omitted: 9>>
>regard; the word lookup is NOT done at runtime but by the function
>BIND, and there is no context hierarchy.
Yes there is. Three examples:
Example 1 for Context Hierarchy:
global-word: "This is the global word."
f: func [f-arg] [
g: func [g-arg] [
print [g-arg f-arg global-word]
]
g "This is g's argument."
]
In this example we are dealing with three contexts: the global context, in
which global-word is defined, the function f's local context in which f-arg
is defined, and finally, the function g, in whose local context its g-arg
is defined.
The g function inherits f's context table in which f-arg is defined.
Therefore g has access to all three words: It can access global-word,
because global-word is defined in the global context, and g has access to
the global context. It can access g-arg, because g-arg is defined in its
own private context table. The g function also has access to f-arg, which
is defined in f's local context. The g function accesses f-arg in f's
context table, which g inherits.
When I evaluate f with the argument "This is f's argument" I get the
following:
>> f "This is f's argument"
This g's argument. This is f's argument This is the global word.
>>
The g function found g-arg in its own context table, it found f-arg in the
context table of the function in which it was created, f's context table,
which g inherited, and it found global-word in the global context. This
shows that REBOL does support a context hierarchy, when it is dereferencing
("looking up") words.
Example 2 for Context Hierarchy:
f: func [x] [
g: func [y] [
x: y
]
g "this is g's argument."
print x
]
When I run this function I get:
>> f "this is f's argument"
this is g's argument.
Note what is happening here. The g function has its own context table. It
is passed the argument "this is g's argument". It sets x, which is defined
in f's context table, to the string "this is g's argument." Then f prints
the value of x, and that value is the value that was set by g. Context
hierarchies work in both directions, getting and setting words.
Your counter example:
>Anyway, I can prove that there is no context hierarchy:
>>> a: 1 b: 1 c: 1
<<quoted lines omitted: 16>>
>If contexts where organized hierarchycally the output would have
>been "2 2 2".
is based on the assumption that "embedded" objects are created in the
context of their "parent" objects and inherit the parent object's context.
This is not the case - as your example indeed demonstrates. The set-word
obj2 is indeed defined in obj1's context, but the object it references
(make object! [...]) is not created in obj1's context.
The same thing goes for obj2. The set-word obj3 is created in obj2's
context, but the object it references does not inherit obj2's context.
In other words, the object referenced by obj1 has two context tables, the
global context table, and its local context table. The object referenced by
obj2 again has two context tables, the global context table and its local
context table. It does not inherit obj1's context table. Finally, the
object referenced by obj3 also has access to the global context table and
to its own local context table. It does not inherit obj1's or obj2's
context tables.
In this (and other) respect(s) objects are different from functions.
Whereas objects created in an object (or function) do not inherit the
parent's context table, functions that are embedded in a local context
inherit the context table of the value they are embedded in. A function
inherits the context of an object it is defined in. A function also
inherits the context of a function it is defined in. We saw an example for
an embedded function inheriting a parent's function context. Here is a
mixed example, in which embedded functions inherit a parent object's context.
Example 3 for Context Hierarchy:
a: 1 b: 1 c: 1
context-1: make object! [
a: "this context-1's a."
context-2: func [/local b] [
b: "this context-2's b."
context-3: func [/local c] [
c: "this is context-3's c."
print [a b c]
]
context-3
]
]
>> context-1/context-2
this context-1's a. this context-2's b. this is context-3's c.
In contrast to your example, in this case the statement print [a b c]
evaluated within the context of context-3 (a function, not an object)
reports the values of a b c that were acquired at its own and at higher
levels of the context table hierarchy.
In summary, functions are evaluated in a context hierarchy, objects are
not. Recall that I was discussing the behavior of recursive functions with
Ladislav, not the behavior of objects. My statements regarding context
table hierarchies are correct with respect to functions.
As a side-effect, functions demonstrate that there does exist a context
table hierarchy mechanism in REBOL. You show that this mechanism is not
effective with respect to objects, not that it does not exist altogether! I
show that it exists, and that it is effective with respect to functions.
> r> Multiple "Context Tables" At the time REBOL enters the
> r> function a new "Context Table" becomes effective. This context
<<quoted lines omitted: 5>>
>always effective, even if it is changed every time the function is
>called.
Well, you kind of figured that out by yourself. I demonstrated that the
function's context table is created at the time the function is defined,
before it is evaluated. The context table I show for the function at that
time it is defined, but before it is evaluated is:
word | value
x | unassigned
y | unassigned
The words x and y are arguments of the function. When the function is
evaluated with the arguments 1 and 2, then - and only then - the function's
context table associates the word x with the value 1 and the word y with
the value 2. The context table of the function at the time it is called
with the arguments 1 and 2 - and only then - becomes
word | value
x | 1
y | 2
>You can refer to previous messages in this list by me,
>Ladislav and Brian about the working of function contexts, in
>particular in the case of recursive functions.
I'll check into it. In the meantime, don't be so lazy. Do your insights
differ significantly from mine? If so, in what respect?
Perhaps my mental model of context tables and the context table hierarchy,
multiple context tables that are effective during recursive function calls,
and the stack in which the context tables that are currently defined for a
function are stored, while it is recursively being evaluated, is a good
model to understand recursive function calls?
What do you think?
> r> If REBOL created a private context table for the function at
> r> the time the function was defined, then it will not be able to
<<quoted lines omitted: 6>>
> word | value
> x | unset!
My notation intends to report that no value was assigned to 'x. Feel free
to use unset! where I use "unassigned".
> r> What we should note here is that apparently REBOL remembered
> r> all three context tables for the function f, even while it was
<<quoted lines omitted: 5>>
>context table is reused. So the function has still only one
>context table in any time, but keeps a stack of values.
Gabriele, it's obvious that more things are being remembered than just
values!
1. The association of words with values is being remembered!
2. The fact that the association of these words with these values is
effective for this particular function is being remembered.
1 and 2 together is by my definition a private context table for the
function. I was not proposing that REBOL has some internal structure called
a context table.
I was only using the term "context table" as a means of describing REBOL's
behavior. Whatever it is that REBOL implements, it looks, walks, smells and
talks like a context table.
I introduced the idea of a "context table" to express a function's
currently effective, or active, bindings of words with values. Now you tell
me that, no, not the context table, BUT the association of words with
values is remembered? These are not two things. The association of words
with values is what I defined as a context table. So if the association of
words with values is indeed being remembered, then the context table, which
is just a mental model, a shortcut to say association of words with values,
then the context table is being remembered because "context table" is just
another way of saying the word/value pairs are being remembered.
3. The context tables (or word/value pairs) that were effective for a
function during a previous evaluation of the function are remembered during
recursive function calls.
As a function steps out of lower-level recursive function call back into
the recursion level from which it was called, the context table that was
associated with the function at the time the called itself recursively,
once again becomes the currently effective context table for this function.
I proposed the model of stack of context tables, to describe REBOL's
behavior with respect re-activating context tables when it returns to
previous recursion levels.
> r> Then we 'a associated with the current-recursion level, and
> r> subsequently called f recursively. If f continued to use its
<<quoted lines omitted: 5>>
>Creating a new context table would require a new binding of the
>function body.
In my model a function is bound to a context. The context is described by a
context table. The function's binding to the context is not impacted, when
the table describing the context is changed.
>Only the value column is stored in a stack and
>reinitialized, as happens when the function is called the first
>time.
Ths is an implementation issue and does not touch on the descriptive
quality of the theoretical model. Is anything gained with respect to
discussing a behavior model of recursive function calls by arguing about
how that model is implemented?
I think the question should be, does the model allow you to correctly
predict the behavior of recursive function calls? Does it do so with a
minimum of theoretical constructs? Is the model simple to understand?
Take Care,
;- Elan [ : - ) ]
[2/22] from: rebol:techscribe at: 23-Jul-2000 0:50
Hi Alex,
does the show-context-table function work for you?
;- Elan [ : - ) ]
[3/22] from: kgd03011:nifty:ne:jp at: 23-Jul-2000 20:55
Hi Elan,
You wrote:
>Example 1 for Context Hierarchy:
>global-word: "This is the global word."
<<quoted lines omitted: 15>>
>is defined in f's local context. The g function accesses f-arg in f's
>context table, which g inherits.
I think it's needlessly complex to say that the g function "has access
to f-arg". It's much simpler to say that the word 'f-arg is bound to the
context of the function F, and that the function G has no privileged access
to that binding of 'f-arg by being within some kind of hierarchy.
(The binding of 'f-arg of course took place even before the function G
was created.)
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.
See you,
Eric
[4/22] from: ole_f:post3:tele:dk at: 23-Jul-2000 7:15
Hi Brett, 19-Jul-2000 you wrote:
>> Thanks! In the meantime, I got it working by simply having the temporary
>> variables as parameters to the function. Mean, but it works.
>You don't need temporary variables. You can use local function variables.
[...]
I did briefly try this, but it seemed to give the same errors. Though now I've
written a bug report to feedback (about 'use), and I just tried writing a
small program which used local function variables, and it seemed to work. So
I probably had another problem in the program...
Kind regards,
--
Ole Friis <[ole_f--post3--tele--dk]>
Amiga is a trademark of Amiga Inc.
[5/22] from: ole_f:post3:tele:dk at: 23-Jul-2000 7:19
Hi Ladislav, 19-Jul-2000 you wrote:
[...]
>> Do you know if this problem has already been reported to
>feedback?
[...]
>You should probably report it to feedback. BTW, did you succeed to
>sort the permutations correctly?
Yup, the compression and decompression work like a charm now. Although the
compression process is extremely slow on normal-sized text documents - it
would probably give quite a speed-up if I could use sort/compare (which runs
the sorting algorithm itself natively) instead of a custom-written sorting
algorithm.
Anyway, I'll report the 'use bug to feedback, then!
Kind regards,
--
Ole Friis <[ole_f--post3--tele--dk]>
Amiga is a trademark of Amiga Inc.
[6/22] from: lmecir:geocities at: 23-Jul-2000 18:25
Hi Elan,
your Mental Model looks elaborated. The problem is, that it
doesn't describe the behaviour of Rebol 2.x correctly (no offense
meant). I could discuss it, but the problem is, that your Mental
Model's notions of "Context Table", "Value Bindings", "Currently
Active Context", "Effective Context Table" "Context Table Stack"
are not very useful for explaining the behaviour of Rebol Contexts
correctly. Instead of using your text and proving some errors, I
am writing a correct description of what is going on, which I find
more useful and less misleading for anyone watching the
discussion.
Next time.
Ladislav
> Hi Ladislav,
>
> thanks for your response.
>
> In the message you were responding to, I was commenting on your
recursive
> function example. Why then did your response include a
*non*-recursive
> function - your second example - that contains an embedded fun2
in a parent
> fun1? Both functions have an argument called x. Were you trying
to
> demonstrate that each of the two x's retain their respective
binding, which
> is local to their respective functions? I was not disputing
that.
> Certainly the two x's are bound in different contexts. The first
'x in
> fun1's context and the second 'x in fun2's context. Given that
each 'x is
> bound in a different context, and the context of both x's is
extended by
> appending them to the block blk, reduce [x x] returns the block
[2 1],
> demonstrating that each of the two x's retained their binding,
and
> therefore each 'x evaluates to the value it is associated with
by virtue of
> being bound bound in the context of the function it is
associated with.
> Perhaps you felt it necessary to demonstrate non-recursive
function calls,
> because you misunderstood me? To set the record straight:
> 1. Identical tokens that are bound in different contexts ('x
bound in fun1,
> 'x bound in fun2) retain their respective values.
> 2. I am not claiming that in recursive function calls those
words that are
> local to the function being called recursively are duplicated
during the
> recursive call.
>
> You appear to comment on something I said:
>
> >As you pointed out, there is a conflict of two things:
> >"Static Context Binding" vs. "Dynamic Value Binding". As a
> >consequence, Use may misbehave during recursive calls.
>
> Interestingly you agree here with something I never said, nor
intended to
> say. Apparently you did misunderstand me. Maybe I did not
explain what I
> meant well enough.
>
> Since I am not sure where the misunderstanding begins, let me
start with
> the basics. I'll present my "mental model" of contexts and
discuss context
> behavior of recursive function calls within the context of my
mental model,
> as I understand it.
>
> My understanding is that the two things that are bound in a
context are a
> word and a value. The relationship between them is loosely
referred to as a
> "binding". A "context" is simply the total of all currently
valid or
> effective bindings. The "Currently Active Context" is the
complete list of
> all word-value pairs that answer the two questions:
>
> 1. When I evaluate the following statement, which words are
currently bound
> to values?
> 2. When I evaluate the following statement, what values are the
currently
> bound words currently associated with?
>
> You can think of a context as a table consisting of two columns,
a word
> column and a value column.
>
> Given the assignments:
>
> >> a: 1
> >> b: 2
> >> c: func [x y] [+ x y]
>
> The Currently Active Context Table would include the following
new bindings:
> word | value
> . | .
<<quoted lines omitted: 4>>
> c | func [x y] [+ x y]
> There exists a Context Table that is always effective, which is
therefore
> called the "Global Context Table". At times, there may be
additional
> context tables effective, "Private Context Tables". The bindings
defined in
> "Private Context Tables" override the bindings defined in the
Global
> Context Table
.
> >From the point of a statement that is being evaluated, there
exists a
> hierarchy of "Effective Context Tables". The lowest Context
Table in this
> hierarchy will first be used to search for the value of a word,
and if the
> word is not found in this context table, the search will
continue in
> context tables at higher levels in the context table hierarchy.
The lowest
> table in the context table hierarchy is the context table that
was last
> created, "last" in terms of previous statements that were
evaluated.
> When REBOL identifies a word in its input stream, it replaces
that word by
> the value that word is bound to (and in some instances evaluates
that
> value, i.e. functions, actions, primitives). In terms of our
Context
> Table
, when REBOL evaluates a word, it looks up the value of
the word in
[7/22] 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."
<<quoted lines omitted: 14>>
>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
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
<<quoted lines omitted: 5>>
>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
[8/22] from: carl:rebol at: 24-Jul-2000 15:40
That looks like a bug. -Carl
[9/22] 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]
<<quoted lines omitted: 27>>
>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 [ : - ) ]
[10/22] from: rebol:svendx:dk at: 24-Jul-2000 3:34
Hello Elan,
Please see comments below.
On 23-Jul-00, [rebol--techscribe--com] wrote:
> Hi Eric,
> you wrote:
<<quoted lines omitted: 80>>
> the word's definition there, it searches in the next-higher context table,
> and so on, until it arrives at the global context table.
Please let me interrupt. A few days ago, I'd have said the same thing, but some experiments
I've done in the last couple of days (and the thread "REBOL's scoping rules") have convinced
me othervice.
I agree that some sort of hierarchy exists, but maybe it just "seems to be".
I'd like to go thru an example, but to do that, I must make the presumption that each
lit-word in REBOL can have it's own private binding (ie. each word can be bound to a
specific context).
The BIND function can be used to modify a words binding. (I which I could express this
better, but well, I can't :-)
First the sample script:
REBOL []
x: "global x"
y: "global y"
code-1: [print [x y]]
f: func [x] [
code-2: [print [x y]]
do code-1
do code-2
g1: func [y] code-1
g2: func [y] code-2
g1 "g-arg-y"
g2 "g-arg-y"
]
f "f-arg-x"
Ok, I'll try to explain what I *belive* goes on during the loading and execution of this
script.
I'll be using a notation like [x--global], which means: lit-word 'x bound to the global
context, and [x--f] means 'x bound to the context of the function f refer to.
even though it'd be more correct to write "[print--global]", I'll just write "print" to
ease reading.
(print, do, func, etc never changes their binding in this example).
Immediatly after the script have been loaded, I belive the situation is like this:
REBOL []
x: "global x"
y: "global y"
code-1: [print [[x--global][y--global]]]
f: func [[x--global]] [
code-2: [print [[x--global][y--global]]]
do [code-1--global]
do [code-2--global]
g1: func [[y--global]] [code-1--global]
g2: func [[y--global]] [code-2--global]
[g1--global] "g-arg-y"
[g2--global] "g-arg-y"
]
[f--global] "f-arg-x"
All words are bound to the global context.
Now execution begin, x, y and code-1 is assigned values in their present context (the
global one).
Let's skip to the line "f: func [x] ["
A new context is created by "make function!", and the args block is scanned for all lit-words.
All lit-words found is then added to the newly created context. (The binding of these
words is irrelevant, since they aren't evaluated).
In this case the only word created in the new context is 'x.
Afterwards, the code-block is recursivly traversed, binding all words in the new context
to that context.
Here's what the code looks like after this re-binding:
(skipping most unchanged lines)
...
f: func [[x--global]] [
code-2: [print [[x--f][y--global]]]
do [code-1--global]
...
code-1 and code-2 are no longer identical, as 'x in the block refered to by code-2 now
is bound in context:x (let's just call it that).
Nothing more is done (I guess) until f is called by the line 'f "f-arg-x"'
I'll skip the two "do code-x" lines for now and skip to the point after the two g-functions
has been created:
(Also I've manually "reduced" some of the words to their values)
REBOL []
x: "global x"
y: "global y"
code-1: [print [[x--global][y--global]]]
f: func [[x--global]] [
code-2: [print [[x--f][y--global]]]
do [print [[x--global][y--global]]]
do [print [[x--f][y--global]]]
g1: func [[y--global]] [print [[x--global][y--g1]]]
g2: func [[y--global]] [print [[x--f][y--g2]]]
[g1--global] "g-arg-y"
[g2--global] "g-arg-y"
]
[f--global] "f-arg-x"
The output of the script is:
## do %test.r
global x global y
f-arg-x global y
global x g-arg-y
f-arg-x g-arg-y
The point is, each litteral word always has exactly one context to which they're bound.
Nothing more is needed in the above example in order to correctly lookup the value of
a given word.
This ofcourse adds some overhead at context creation time, because words in deeply nested
blocks can end up being bound several times, but given the speedup in word-lookup (one-level)
- it's certainly worth it.
>> (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.
No, it's really the same thing. when function f was created, all occurences of f-arg
was bound even in the code-block of g and since g didn't later rebind it, it remained
bound to the context of f.
(I hope I got it right this time - I've changed my mind over this matter a couple of
times :-)
-- snip --
Best regards
Thomas Jensen
[11/22] from: agem:crosswinds at: 25-Jul-2000 15:56
[rebol[author: "Volker"]
{seems 'make does no deep binding? without bug this
should set 'b in object-context too (hopefully)?}
unset 'b
a: make object! [if not value? 'b [b: "a bee!"]]
b
a/b
]
>> unset 'b
>> a: make object! [if not value? 'b [b: "a bee!"]]
>> b
== "a bee!"
>> a/b
** Script Error: Invalid path value: b.
** Where: a/b
[12/22] from: lmecir:geocities at: 25-Jul-2000 16:49
Hi Volker,
no, the behaviour is correct. Try this:
unset 'b
a: make object! [b: none unset 'b if not value? 'b [b: "a bee!"]]
a/b
[13/22] from: giesse:writeme at: 25-Jul-2000 19:21
Hello [carl--rebol--com]!
On 25-Lug-00, you wrote:
c> That looks like a bug. -Carl
Hmm... do you have some little spare time to tell us how contexts
work? Isn't binding done word-by-word? Isn't hierarchy achieved by
multiple pass binding?
You're confusing me, now. :-)
Regards,
Gabriele.
--
Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer
Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[14/22] from: lmecir:geocities at: 25-Jul-2000 21:07
Me too.
[15/22] from: larry:ecotope at: 25-Jul-2000 13:24
I have been confused for a long time about contexts (touted as an important
feature of the REBOL language) and the related issues concerning 'bind. It
seems to me that a good explanation of the workings of contexts from RT is
long overdue.
At least tell us if this is for sure a bug and if it is what should have
been the output from Gabriele's example. Should it have been [2 2 2]?
More confused than ever :-(
-Larry
[16/22] from: deadzaphod:ho:tmail at: 26-Jul-2000 4:08
>Hello [carl--rebol--com]!
>On 25-Lug-00, you wrote:
<<quoted lines omitted: 5>>
>Regards,
> Gabriele.
Confusing me too... that behavior was exactly what I would have expected and
wanted. (I haven't been posting on this thread so far, but I happened to
figure out how contexts work about 2 days before this started, having
previously been badly confused)
BTW: Gabriele - I agree with you completely on your explanations so far on
how binding/contexts in rebol work.
- Cal ([deadzaphod--hotmail--com])
[17/22] 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:
http://www.TechScribe.com
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"
<<quoted lines omitted: 10>>
>** 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,
<<quoted lines omitted: 8>>
>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
<<quoted lines omitted: 3>>
>[...]
>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
<<quoted lines omitted: 11>>
>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
2
>> obj1/a: 100
== 100
>> obj1/obj2/b
== 2
>> obj1/obj2/f 1
101
> r> Perhaps my mental model of context tables and the context
> r> table hierarchy, multiple context tables that are effective
<<quoted lines omitted: 3>>
> 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
<<quoted lines omitted: 10>>
>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 2.0.4.1.1
<<quoted lines omitted: 32>>
>== 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
http://www.REBOLpress.com
visit me at http://www.TechScribe.com
[18/22] from: lmecir:geocities at: 26-Jul-2000 18:43
The following has been written:
> > Hi Ladislav, 15-Jul-2000 you wrote:
> >
<<quoted lines omitted: 6>>
> >
> > Judging from the nature of recursiveness, that's a little
hard,
> isn't it? ;-)
> >
<<quoted lines omitted: 5>>
> > Ole Friis <[ole_f--post3--tele--dk]>
> >
here is a pretty simple example showing the problem:
temporary: "global temporary"
recfun: func [level] [
use [temporary] [
if level < 1 [
temporary: "temporary"
recfun level + 1
print ["Temporary:" temporary]
]
]
]
recfun 0
; The result:
** Script Error: temporary has no value.
** Where: temporary
; let's define a function r-use like this:
r-use: func [
"Defines words local to a block."
words [block!] "Local word(s) to the block"
body [block!] "Block to evaluate"
] [
do function [] words body
]
; and now use R-use instead of native Use
temporary: "global temporary"
recfun: func [level] [
r-use [temporary] [
if level < 1 [
temporary: "temporary"
recfun level + 1
print ["Temporary:" temporary]
]
]
]
recfun 0
; The result:
Temporary: temporary
Ladislav
[19/22] from: lmecir:geocities at: 26-Jul-2000 19:38
Hi Elan,
you wrote:
> (...)
> 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.
>
I think, that here is the main difference between your "Mental
Model Approach" and our approach:
We, not having the official description, are writing the
description of Rebol behaviour, while you are trying to describe
the "Intended Behaviour", that surely differs. Problem with your
approach is, that you neither know the Rebol "Intended Behaviour"
not being its creator, nor are able to correctly describe the
actual behaviour, because you don't even try to do it.
Regards
Ladislav
> >>> f-arg: "Global f-arg!"
> >== "Global f-arg!"
<<quoted lines omitted: 6>>
> >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).
<<quoted lines omitted: 10>>
> >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.
> >
<<quoted lines omitted: 4>>
> >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
[20/22] from: giesse:writeme at: 26-Jul-2000 19:23
Hello [rebol--techscribe--com]!
On 26-Lug-00, you wrote:
r> I've set up a mailing list on my Web server for the book (for
r> bug fixes and clarifications and ongoing discussions).
Good. I think I'll subscribe eventually. :-) Anyway, I'm quite
sure it'll be very difficult to find bugs in your book. :-)
r> After reading your email carefully, my impression is that our
r> main discrepancy has to do with perspective. I view REBOL as a
r> programming language, and I think about REBOL in terms of
r> concepts, principles that lend themselves to describe how
r> REBOL acts as a language.
r> In contrast, you apparently think about REBOL as an
r> interpreter implementation. You tend to speculate about how
r> the REBOL interpreter is likely to implement some language
r> feature.
This is likely to be right. OTOH, the presence or not of a
hierarchy of contexts might make some differences if you're using
BIND in your script; also, the fact that the binding is static
makes it possible to mix words from different contexts in the same
block and run that block "outside" of those contexts. This is
rarely done currently only because of the (in)famous GC bug.
r> Carl commented on a similar example you provided while binding
r> a block to an embedded object, and declared the bind behavior
r> you demonstrated to be a bug. He didn't clarify, and I will
r> rely on his response
Yup, and this really confuses me. If you think about it, the
current behaviour makes sense, and the model proposed by me,
Ladislav and Brian greatly simplifys the runtime environment of
the interpreter as opposed to a dynamic lookup and a hierarchy of
contexts.
[...]
r> Hierarchic context table inheritance
r> is REBOL's intended behavior.
But well, it never worked this way since 2.0. It really seems very
strange to me that Carl didn't notice before; I really hope he'll
clarify on this.
r>>>> f-arg: "Global f-arg!"
r>> == "Global f-arg!"
r>>>> print bind [g-arg f-arg global-word] g's-context-word
r>> This is g's argument. Global f-arg! This is the global word.
r>>
r>> So, how does it work when calling F? When F is created, a new
r>> context table is created.
r> Thank you. I went to pains to demonstrate that.
I never meant to negate this. I'm sorry if I seemed to. You know,
I'd still need some English lessons. :-)
r>> Then the BIND function is called to bind
r> Metaphorically speaking? I have never seen the bind function
r> called during the construction of a function. If you source
r> func and function, you will find that neither of these
r> mezzanine functions call bind. They both use make function!
r> ... and I have no access to the code that is executed when
r> make function! is called.
I mean that MAKE FUNCTION! internally calls the same C routine
called by the native BIND function.
r> I think this is a conceptual problem. There is no g-arg
r> defined in the global context. Accordingly "g-arg" was never
r> bound to the global context. Therefore "g-arg" cannot "still"
r> be bound to the global context.
This is wrong. Look:
>> f: func [f-arg] [
[ g: func [g-arg] [
[ print [g-arg f-arg global-word]
[ ]
[ g "This is g's argument."
[ ]
>> print mold first system/words
[end! ... f f-arg g g-arg global-word] ; snipped for brevity
There's a global g-arg, and its value is:
>> type? get/any 'g-arg
== unset!
r>> When F is executed, the function G is created, and thus the
r>> block above gets bound to G's context. Again, only the word
r>> "g-arg" is affected, while "print" and "global-word" are left
r>> bound to the global context and "f-arg" to F's context.
r> Thank you. Note what you are saying here. You are looking at
r> this from a different perspective, an implementation
r> perspective, - nevertheless - you are formulating a mechanism
r> that exactly results in context inheritance.
Indeed, what I said before is that "context inheritance" is just a
side effect in the current implementation, not the result of a
memory structure that can be identified as a "Context Hierarchy".
You're absolutely right that mine is an implementation
perspective, but there's a huge difference between a model based
on dynamic word lookups and a model based on static word bindings.
r> Your
r> implementation view (though speculative, but reasonable)
r> supports my conceptual representation, don't you think?
Yes. But you get different results when you're using BIND
manually.
r> Now "No hierarchy NEEDED" has become the "same" as proving
r> "there's no hierarchy here:"? After describing a speculative
r> process (albeit a reasonable one) that brings about a
r> behavior, which can be described - with precision - as a
r> context table hierarchy, you have lowered your attack from "I
r> can prove that there is no context hierarchy" to "no hierarchy
r> needed"?
Oh, don't be so picky. :-) I cannot know what REBOL actually does,
I'm just proposing the most reasonable model. And that model does
not need any context hierarchy to fully explain REBOL --- the
hierarchy you see is a side effect.
It's just that I don't think they're using a model that is so much
complicated to look like it didn't use a hierarchy while it's
using it.
r> Perhaps having thought through a process through which REBOL's
r> hierarchical context behavior may be implemented, your
r> opposition to this concept has become weaker, from proving
r> "there's no hierarchy" to avoiding the hierarchy use of the
r> word hierarchy, "no hierarchy needed"?
I think the current implementation has no hierarchy. (Probably
this is a bug as Carl said, I don't know.) That is, the C
structure that represents a context table has no pointer back to a
parent context table. Instead, what you SEE as a context hierarchy
is the SIDE EFFECT of binding the same block multiple times.
I hope I've been clearer this time. :)
[...]
r> Note that print [a b c] does not occur in the object.
But putting that in the object would have produced the same
results. As in:
>> a: 1 b: 1 c: 1
== 1
>> obj1: make object! [
[ a: 2
[ obj2: make object! [
[ b: 2
[ obj3: make object! [
[ c: 2
[ code: [print [a b c]]
[ ]
[ ]
[ ]
>> do obj1/obj2/obj3/code
2 2 2
r> How does your example above prove anything with respect to
r> context table hierarchies and objects? The expression print [a
r> b c] is evaluated at the time the objects are being
r> constructed and does not survive the construction process.
r> Therefore the construction process of objects determines the
r> context in which print [a b c] is evaluated, and not the
r> context of the resulting objects.
I hope the example above is clearer.
r>> There's
r>> absolutely no difference between a function's context and an
r>> object's context.
r> Actually there is! Observe:
r>>> obj1: make object! [
r> [ a: 1
r> [ obj2: make object! [
r> [ b: a + 1
r> [ f: func [x] [ print a + x ]
r> [ ]
r> [ ]
r>>> obj1/obj2/b
r> == 2
r>>> obj1/obj2/f 1
r> 2
r>>> obj1/a: 100
r> == 100
r>>> obj1/obj2/b
r> == 2
r>>> obj1/obj2/f 1
r> 101
I'm sorry, I can't see any difference in the contexts here. It's
just that B is an integer! while F is a function!.
r>> It is accurate enough,
r> Thank you!
r>> except for the hierarchy.
r> This objection should by now be layed to rest! It's a bug.
Hmm.
r> This is not my issue. I'm not trying to outguess the REBOL
r> interpreter architecture. My only concern is in finding a
r> useful representation for how the language works. And with
r> respect to that, I think that it does not make a difference if
r> the interpreter indeed saves and stores context tables and
r> does/or does not bind its body at each recursion.
That's ok for me.
r>> Of course, if you think in terms of dinamic binding this
r>> makes no sense, so we should find an an agreement on that
r>> first. :)
r> Since you raise this as an issue, go ahead ;-).
Oh, I think binding is static. Do you agree? ;^)
r> "it does the lookup at bind time." I'm not sure what you mean
r> by that.
The BIND function does word lookup in context. The DO function
probably doesn't even know about contexts --- it just evaluates
the values the words were boud to.
[REBOL 2.0]
r>>>> obj: make object! [x: 1]
r>>>> word: in obj 'x
r>> == x
r>>>> get word
r>> == 1
r>>>> probe obj
r>>
r>> make object! [
r>> x: 1
r>> ]
r>>>> first obj
r>> == [self x]
r>>>> change next first obj 'a
r>> == []
r>>>> probe obj
r>>
r>> make object! [
r>> a: 1
r>> ]
r>>>> get word
r>> == 1
r>>>> word
r>> == x
r>>
r>> So, how is that?
r> The context was extended. That explains how x remains bound to
r> 1.
I think I don't understand completely what you mean here. You mean
that the context was extended to contain BOTH the words 'a and 'x?
If this was the case, if we bind the word 'x to the object's context,
do you expect to get 1 again?
r> I'm cc'ing you the message, just in case ... :-).
Thanks. But now things get worse for me: I got the message from
the ml but didn't get the CC from you. So this means the problem's
on my side, and I could have lost other private messages too (I
considered this unlikely because I don't see the same problem with
other mailing lists, but perhaps I've lost messages from them too
without noticing...).
I've got to track this down.
Regards,
Gabriele.
--
Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer
Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[21/22] from: lmecir:geocities at: 26-Jul-2000 20:11
Hi,
The discussed code:
f: func [f-arg] [
g: func [g-arg] [
print [g-arg f-arg global-word]
]
g "This is g's argument."
]
Gabriele:
> >So when F is created
> >the block:
<<quoted lines omitted: 7>>
> >bound to F's context, while "print", "g-arg" and "global-word"
> >aren't changed (so they're still bound to the global context).
Elan:
> 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.
Here is a proof:
>> global? probe first second fourth second :f
g-arg
== true
Regards
Ladislav
[22/22] from: lmecir:geocities at: 26-Jul-2000 21:41
Hi,
Gabriele:
> >Then the BIND function is called to bind
>
Elan:
> 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.
You have never seen just because you didn't try. See the
following:
code-block: [
f: func [f-arg] [
g: func [g-arg] [
print [g-arg f-arg global-word]
]
g "This is g's argument."
]
]
do code-block
f-body: second :f
f-body-f-arg: probe second second fourth f-body
f-body-template: fourth code-block
bound-f-body-template: bind/copy f-body-template f-body-f-arg
same? first bound-f-body-template first f-body
same? second bound-f-body-template second f-body
same? first third bound-f-body-template first third f-body
same? first fourth bound-f-body-template first fourth f-body
same? first second fourth bound-f-body-template first second
fourth f-body
same? second second fourth bound-f-body-template second second
fourth f-body
....
But:
same? second second fourth f-body-template second second fourth
f-body
Ladislav
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted