[REBOL] Re: Binding
From: ladislav:mecir:vslib:cz at: 19-Nov-2002 18:35
Hi Robert,
> Let's get back to my first code snippet:
>
> forall-records: func [list predicate action /local object][
> if any [none? list empty? predicate empty? action][return none]
>
> list: select list 'values
>
> predicate: bind/copy predicate 'list
> action: bind/copy action 'list
>
> ; iterate through the whole list of values
> ; check if the first entry satisfies the predicate
> ; if so execute the action.
> foreach [id object] list [
> if do predicate [do action]
> ]
> ]
>
> result: make block! []
> forall-records graph/nodes [?? object][append result id]
>
> And see what I think we have (please correct if wrong):
> 1. result is bound to the global context
Look out! A sentence like this can have no sense at all! Look at the
following example, try it at the console:
sample-block: [x]
append sample-block use [x] ['x]
sample-block ; == [x x]
Now we see, that SAMPLE-BLOCK contains two words. Can we say "SAMPLE-BLOCK
is bound to the global context"? No way! Let's make sure:
x: 1
get sample-block/1 ; == 1
, if we try the same for the second word, we obtain:
get sample-block/2
** Script Error: x has no value
** Near: get sample-block/2
So, can we say, that SAMPLE-BLOCK isn't bound to the global context? This
looks wrong, again, because the first word clearly *is bound to the global
context*.
What always makes sense is a question: "To which context is bound the first
word of the SAMPLE-BLOCK?", or "To which context is bound the second word of
the SAMPLE-BLOCK?", because words always have a context attribute, i.e. an
information, to which context they are bound.
> 2. Are OBJECT, RESULT and ID bound at all? Where? Global context?
A general answer is: every Rebol word is either unbound or it is bound to a
context.
Nevertheless, your question is potentially dangerous, because you didn't
*exactly* specify the words you meant. If you meant something like:
Is the word 'object that can be found at:
foreach [id object] list [
(the second element of the block following the word 'foreach) bound to the
global context?
, it makes more sense, but the question is still ambiguous.
If you allow me to suppose, that you are referring to the body of the
FORALL-RECORDS function, I would answer no. Then I can say, that the word
'object is bound to the local context of the FOREACH-RECORD function,
because of the /local object part of the function specification.
If you ask me about the binding of a word 'object, that can be found in the
PREDICATE block, the answer is the same, after the binding in:
predicate: bind/copy predicate 'list
is evaluated. Your trouble is, that this binding doesn't help you to achieve
what you probably want to.
If you ask me the same question about the word 'id, the correct answer is:
I have got no idea!
> 3. Now the function call happens. LIST PREDICATE ACTION are set
> as aliases to
> - graph/nodes
> - [?? object]
> - [append result id]
No aliases in this case, the variables simply refer to the corresponding
values (alias is a specific notion in Rebol, that doesn't apply to this
situation).
> 4. action will be set to a copy of [append result id] with the words
> bound to ??
>
> And now I'm lost...
>
> Is there a graphical picture that shows how all this binding etc. stuff
> works together? I said one-shot because IFAIK the binding of a word
> can't be changed once set.
This is something I should explain a bit. Let's have a look at the
SAMPLE-BLOCK as created above. It contains two words, which are bound to
different contexts, although the words "look the same":
same? sample-block/1 sample-block/2 ; == false
It is pretty easy to replace the second word as follows:
sample-block/2: sample-block/1
What is the result of this operation? Both words in the SAMPLE-BLOCK now
have the same binding, they are bound to the same context! This means, that
I changed the SAMPLE-BLOCK substantially, although I didn't try to change
the binding of the second word, because I simply replaced it.
I may say, that I changed SAMPLE-BLOCK, by replacing its second word. This
means, that Rebol blocks are dynamic, you can change them, and you often do,
while Rebol words are being replaced.
> > No such information exists. A block can contain words. Every
> > word in a block has its own binding attribute.
> Ok, that's something I can imagine. Is there a binding visualizer
> available? I would like to see where a word is bound to, not only get
> the message: It's not bound to the actual context.
I can offer you only the following means to visualize context: UNBOUND?,
GLOBAL?, LOCAL?, EQUAL-BINDING?, IN-OBJECT?, which can tell you something
about words you are checking. These functions are available in my
Contexts.html article at www.rebolforces.com/~ladislav
The trouble with the visualization is, that you can always compare the
binding attributes of two words, but Rebol doesn't offer us any direct way
how to visualize/get the binding of a word.
Moreover "the actual context" is something, that doesn't exist, I am sorry.
A proof:
Let's create SAMPLE-BLOCK again as before, try to execute it and see, what
is going to be the "actual context":
sample-block: [x]
append sample-block use [x] ['x]
sample-block ; == [x x]
do sample-block
** Script Error: x has no value
** Near: x
As we made sure, it wasn't be the Global Context, because the second 'x in
SAMPLE-BLOCK isn't global, OTOH, it couldn't have been any other context,
because the first 'x is global. The only thing we may say is, that the
SAMPLE-BLOCK contains equal words with different binding, IOW, the
SAMPLE-BLOCK may be considered a "mixed context" block.
> > No. FOREACH binds its BODY argument appropriately.
>
> At the moment the body is evaluated the first time?
Correct answer is: "Before it starts to evaluate the body for the first
time."
> > Unfortunately, if you use variables 'predicate and 'action,
> > FOREACH binds only the variables instead of the values they represent.
>
> Hmm... Does this make any sense? What does is mean "binds only the
> variables..." So these have no values at all?
It means this: something like
bind [if do predicate [do action]] 'id
will happen, but it will do nothing, because BIND will find only words: 'if
'do 'predicate, 'action, while it finds neither 'id, nor 'object.
I could have written analogical simulation of FOREACH as I wrote for USE,
but I guess, that you could write it too now.
-L