Binding
[1/23] from: robert:muench:robertmuench at: 18-Nov-2002 17:39
Hi, I have the following code:
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]
]
]
Within predicate and action I would like to have access to id and
object. And from action I would like to have access to the local
variables from the caller's context. I tried the following:
result: make block! []
forall-records graph/nodes [?? object][append result id]
Of course this doesn't work! Problem is that local object isn't
accessible (it's none). I thought that bind is not static (meaning: all
words in the block are bound to the words known until bind was called)
instead will give you access to all local words. But it seems this is
not the case.
Any idea how to solve it the smart way? Robert
[2/23] from: rotenca:telvia:it at: 18-Nov-2002 18:53
Hi Robert,
> Within predicate and action I would like to have access to id and
> object. And from action I would like to have access to the local
> variables from the caller's context. I tried the following:
foreach [id object] list [
if do bind predicate 'id [do bind action 'id]
]
or
foreach [id object] list compose/deep [
if do (predicate) [do (action)]
]
---
Ciao
Romano
[3/23] from: robert:muench:robertmuench at: 19-Nov-2002 9:00
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 8>>
> if do bind predicate 'id [do bind action 'id]
> ]
Hi, I wanted to avoid to bring BIND into the loop. So, it really seems
to be that bind is one-shot action. Every word that get's bound to the
local context after BIND isn't accessible from the bounded block. Is
this correct? If so, I'm wondering why? IMO it must be harder to keep
track of the words that the bounded block can access than just to say:
Ok, the block can access all local words (that are present now and will
come up later).
> foreach [id object] list compose/deep [
> if do (predicate) [do (action)]
> ]
Why does compose work here? Will it execute an implicit BIND? The help
just says it will evaluate the parens. Strange thing... Would it work
with REDUCE as well?
BTW: Thanks for the info ;-). Robert
[4/23] from: lmecir:mbox:vol:cz at: 19-Nov-2002 12:57
Hi Robert,
> > foreach [id object] list [
> > if do bind predicate 'id [do bind action 'id]
> > ]
> Hi, I wanted to avoid to bring BIND into the loop.
yes, it is advisable to avoid bringing BIND into the loop, that is why the
compose/reduce alternative surely looks better
> So, it really seems
> to be that bind is one-shot action.
I am not sure I understand what you mean here...
> Every word that get's bound to the
> local context after BIND isn't accessible from the bounded block.
Again, I don't think, I understand...
> IMO it must be harder to keep
> track of the words that the bounded block can access
No such information exists. A block can contain words. Every word in a block
has its own binding attribute.
> > foreach [id object] list compose/deep [
> > if do (predicate) [do (action)]
> > ]
I think, that it may contain a bug. The correct way might be:
foreach [id object] list compose/deep [
if do [(predicate)] [(action)]
]
> Why does compose work here? Will it execute an implicit BIND?
No. FOREACH binds its BODY argument appropriately. Unfortunately, if you use
variables 'predicate and 'action, FOREACH binds only the variables instead
of the values they represent.
The code containing COMPOSE doesn't allow FOREACH to bind the variables,
because it replaces the variables by their contents before BODY is supplied
to FOREACH, and that is why FOREACH is allowed to do what is needed.
> Would it work
> with REDUCE as well?
Here is a REDUCE version:
foreach [id object] list reduce [
'if 'do predicate action
]
-L
[5/23] from: robert:muench:robertmuench at: 19-Nov-2002 14:24
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 7>>
> > local context after BIND isn't accessible from the bounded block.
> Again, I don't think, I understand...
Hi, ok I try again with the goal to finally understand this. Can't
believe it but even after years of Reboling it sometimes surprises me...
And I just read some of your words, etc. stuff from your Rebol page. But
it's really hard stuff...
Anyway: 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
2. Are OBJECT, RESULT and ID bound at all? Where? Global context?
3. Now the function call happens. LIST PREDICATE ACTION are set
as aliases to
- graph/nodes
- [?? object]
- [append result id]
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.
> 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.
> No. FOREACH binds its BODY argument appropriately.
At the moment the body is evaluated 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?
> The code containing COMPOSE doesn't allow FOREACH to bind the
> variables, because it replaces the variables by their
> contents before BODY is supplied to FOREACH, and that is why
> FOREACH is allowed to do what is needed.
Ok, I think I got this. So I can think of this like doing a textual
replacement (but keeping the origianl binding). Robert
[6/23] from: brett:codeconscious at: 20-Nov-2002 3:18
Hi Robert,
> Hi, ok I try again with the goal to finally understand this. Can't
> believe it but even after years of Reboling it sometimes surprises me...
> And I just read some of your words, etc. stuff from your Rebol page. But
> it's really hard stuff...
I leave it to other to explain that code in more detail. I wanted to provide
some different examples of words and their bindings just in case they help
in understanding. I recommend pasting the script below into the console.
Regards,
Brett.
; The following four lines when executead establish the
; word "greeting" into four different contexts.
greeting: {Hi!}
australia: context [ greeting: {G'day!} greet: does [greeting] ]
france: context [ greeting: {Salut!} greet: does [greeting] ]
sweden: context [ greeting: {Hey!} greet: does [greeting] ]
; instances-of-greeting will contain four values
; of type word! all of which have the same name {greeting}
; but which differ in that each is bound to a different context.
instances-of-greeting: reduce [
'greeting
in australia 'greeting
in france 'greeting
in sweden 'greeting
]
; Visually we might think it is the same word, but internally
; REBOL knows to keep them seperate.
?? instances-of-greeting
reduce instances-of-greeting
; We can create an expression that will evaluate to a single value.
expression: compose/deep [ rejoin [(instances-of-greeting)] ]
; Which can be evaluated like
do expression
; But just because it looks like code doesn't mean we can't treat it
; as data.
get expression/rejoin/1
get expression/rejoin/2
; We can make a function from the expression by using the expression as
; the function body.
f: does expression
f
; Or demonstrate how the words in a function body are bound to the
; function arguments.
g: func [ greeting ] expression
g "Yo"
; Which is like using BIND on the expression itself - lets bind it to
; the swedish context.
new-expression: bind/copy expression in sweden 'self
do new-expression
; BIND changes the context of words in a block, so does FUNC to its
; body block. CONTEXT (make object!) also changes the context of
; words in a block it is given.
; In this next example, treat the script block as data like we did
; before.
currency-name: "Dollar"
script: [
euro-zone: context [
currency-name: "Euro"
print-currency: does [print currency-name]
]
]
get script/context/does/2
; Now see the change after the script block is evaluated.
do script
get script/context/does/2
; End of examples.
[7/23] 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][
<<quoted lines omitted: 13>>
> 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
[8/23] from: robert:muench:robertmuench at: 19-Nov-2002 23:02
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 9>>
> Now we see, that SAMPLE-BLOCK contains two words. Can we say
> "SAMPLE-BLOCK is bound to the global context"? No way!
Hi, of course you are right. As said I'm implicitly using all this quite
in the right way but there are still some black wholes in my mind about
it all and I now decided to fix this ;-). And again, I have programmed
to much in C++ etc. so it's really not quite obvious. And (finally) I
don't like to much implicit stuff I need to know... It makes life hard.
> Let's make sure:
>
> x: 1
> get sample-block/1 ; == 1
Ok, that's clear.
> , 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
Because this x is atifically defined to the local block by use [x]['x],
right?
> 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*.
My mistake was to think of the block as the instance that defines the
context (like a namespace in C++) but in Rebol a block is just a
container. The words inside the block carry the context around. Can this
context be read, printed? Would it be possible to have named contexts?
This would help a lot IMO.
> 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?",
Right. I will print this and tag it to my monitor ;-))
> because words always have a context attribute, i.e. an
> information, to which context they are bound.
And that's the big difference! So I read somewhere in your (very good)
articles that the context of a word can be changed. Is this right? This
would mean that as long as I can get the right context I can use a word
as a named-pointer into this 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.
I see and I understand it step by step...
> This is something I should explain a bit. Let's have a look
> at the SAMPLE-BLOCK as created above. It contains two words,
<<quoted lines omitted: 6>>
> SAMPLE-BLOCK now have the same binding, they are bound to the
> same context!
Ok.
> 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.
And this means that the old word was "overwritten" with a new word that
has a different context. The old word is now nowhere referenced and
therefore can be freed? Or is Rebol still carrying it around as a
word-zombie that can't be accessed anymore?
> I may say, that I changed SAMPLE-BLOCK, by replacing its
> second word. This means, that Rebol blocks are dynamic, you
<<quoted lines omitted: 5>>
> checking. These functions are available in my Contexts.html
> article at www.rebolforces.com/~ladislav
Thanks, I already looked at them and try to understand evey line. I'm
going to play around with it.
> 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.
But we can collect the number of contexts, right? Further we just can
enumerate the contexts and collect all words. From this a graphical
representation should be possible. I would love to have a browser for my
script that shows me all words, which contexts I have etc. Would be very
handy for debugging.
> Moreover "the actual context" is something, that doesn't
> exist, I am sorry. A proof:
I think I now know why: Because the words carry the context around, you
don't have a single place where you enter a specific context and leave
it (namespeace analogy). Instead you have a set of words with a lot of
different contexts, which are used in the actual block.
> Let's create SAMPLE-BLOCK again as before, try to execute it
> and see, what is going to be the "actual context":
<<quoted lines omitted: 10>>
> equal words with different binding, IOW, the SAMPLE-BLOCK may
> be considered a "mixed context" block.
That's a good description. IMO mixed context block describes the
situation very specific.
> Correct answer is: "Before it starts to evaluate the body for
> the first time."
;-)) Ok. I know I need to be as specific as it's necessary.
> I could have written analogical simulation of FOREACH as I
> wrote for USE, but I guess, that you could write it too now.
Thanks a lot for your time and this great WORD training. I'm sure I will
have further questions ;-)). Robert
[9/23] from: carl:s:rebol at: 19-Nov-2002 16:06
Good discussion. Wish I had more time to hang out and read...
At 11:02 PM 11/19/02 +0100, you wrote:
>I think I now know why: Because the words carry the context around, you
>don't have a single place where you enter a specific context and leave
>it (namespeace analogy). Instead you have a set of words with a lot of
>different contexts, which are used in the actual block.
Exactly. It has to be that way. Here's an example of why:
print-block: func [block] [
foreach value reduce block [
print value
]
]
example: has [temp][
temp: 12
print-block [temp now]
]
The contexts of TEMP and NOW have to be carried with them, otherwise they can
not be known within the print-block. This is that "variation" on static
(syntactic)
binding that REBOL uses. It's not precisely static, because it can be modified
at runtime by functions like BIND, MAKE, FUNC, etc.
BTW, named contexts *are* created by MAKE OBJECT... what you want is a way to
pass them as an argument to BIND (rather than a word from the object). An
interesting
(and doable) idea.
-Carl
Carl Sassenrath
Founder & Chairman
REBOL Technologies
www.rebol.com
[10/23] from: lmecir:mbox:vol:cz at: 20-Nov-2002 2:36
Hi Robert,
> in Rebol a block is just a
> container. The words inside the block carry the context around.
Well said.
> Can this
> context be read, printed? Would it be possible to have named contexts?
> This would help a lot IMO.
Of course, you can collect sample words of some contexts and check all words
which context they are from. The trouble is, that some context are "being
created" during the evaluation of a rebol script, which means, that your
collection may never be complete.
Example:
use [x] ['x]
Whenever the USE function is evaluated, it creates a new context, i.e. if
you evaluate the above code line three times, you will create three new
contexts. Sample context-creating functions: USE, MAKE (OBJECT! FUNCTION!),
REPEAT, FOREACH. Any function from the above list creates exactly one
context whenever it is evaluated.
Illustration:
block: []
loop 2 [append block use [x] ['x]] ; == [x x]
set block/1 1
set block/2 2
reduce block ; == [1 2]
> I read somewhere in your ...
> articles that the context of a word can be changed. Is this right?
1) Yes. That is what e.g. BIND normally does for Rebol blocks. It replaces
the words contained in the block by their counterparts bound to the
specified context, if possible.
2) No. You cannot change the context of a word without replacing the word.
(You may ignore this, if it isn't understandable for you ATM)
> I can use a word
> as a named-pointer into this context.
Yes, any word from the specified context will do
> ... the old word was "overwritten" with a new word that
> has a different context. The old word is now nowhere referenced and
> therefore can be freed?
Only the context as whole can be freed. If you have got at least one context
word, you are (at least theoretically) able to get all words of the
specified context using BIND.
> > I can offer you only the following means to visualize
> > context: UNBOUND?, GLOBAL?, LOCAL?, EQUAL-BINDING?,
<<quoted lines omitted: 12>>
> script that shows me all words, which contexts I have etc. Would be very
> handy for debugging.
It might be a good start to colorize the code from the Computed Binding
chapter of Contexts.html, what do you think?
> > Moreover "the actual context" is something, that doesn't
> > exist, I am sorry.
>
> I think I now know why: Because the words carry the context around, ...
> you have a set of words with a lot of
> different contexts, which are used in the actual block.
That's it.
-L
[11/23] from: robert:muench:robertmuench at: 20-Nov-2002 9:36
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 14>>
> The contexts of TEMP and NOW have to be carried with them,
> otherwise they can not be known within the print-block.
Hi, I understand this but it's really different to compiled languages.
In a compiled language this would be called "call-by-reference". BTW:
Are there are any situations where Rebol makes an implicit copy of words
where I loose this "by-reference" semantic?
> This is that "variation" on static (syntactic)
> binding that REBOL uses. It's not precisely static, because
> it can be modified at runtime by functions like BIND, MAKE, FUNC, etc.
And that's what IMO is what "normal" programmers have the biggest
problem with. In C++ a variable name and value is a unit. And if you
don't change the value it won't change (only if you leave a scope). In
Rebol a "variable" (a.k.a word) is just a human-readable-descriptor so
that we can write it down. The value of such a word depends on the
binding, which is dynamic and context-dependent.
> BTW, named contexts *are* created by MAKE OBJECT...
Right, but at the moment these are more containers for words than
useable structures (first-class-object?)
> what you want is a way to pass them as an argument to BIND (rather
> than a word from the object). An interesting (and doable) idea.
Exactly! And if it's doable I highly vote for such a feature! And it
would be nice to be able to query the (named) context of a word for
debugging.
When can we see this feature? :-))) Robert
[12/23] from: robert:muench:robertmuench at: 20-Nov-2002 9:36
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 5>>
> > container. The words inside the block carry the context around.
> Well said.
Hi, :-) fine! It seems that I slowly understand the internal structure
better and better.
> Of course, you can collect sample words of some contexts and
> check all words which context they are from.
Yes, but I need to know about the context ;-)
> The trouble is, that some context are "being created" during the
> evaluation of a rebol script,
That's what I expected now. This is a bit like the "anonymous unions".
And now I see why we have to specify know-words for BIND for example:
The context can't be referenced, only words from the context. We have to
keep track of the contexts in mind. What I realy would like is a
context-querying thing.
> which means, that your collection may never be complete.
>
> Example:
>
> use [x] ['x]
>
> Whenever the USE function is evaluated, it creates a new
> context, i.e. if you evaluate the above code line three
> times, you will create three new contexts.
Ok, and if you don't assing it to a word, your context isn't
referenceable. It will be used implicitly but can't be accessed
explicitly.
> Sample context-creating functions: USE, MAKE (OBJECT! FUNCTION!),
> REPEAT, FOREACH. Any function from the above list creates
> exactly one context whenever it is evaluated.
Is there a list of all functions that create contexts? IMO this would
help a lot to understand all this.
> Illustration:
>
> block: []
> loop 2 [append block use [x] ['x]] ; == [x x]
> set block/1 1
> set block/2 2
> reduce block ; == [1 2]
This code realy looks crazy to people not used to this. So it would be
possible to write a program only using the word X in different contexts.
I don't want to reverse engineer such a code ;-).
BTW: Do you think it would be possible to write a function that
minimizes the number of contexts for a rebol script? And that replaces
as much words with the same name as possible.
> > I read somewhere in your ...
> > articles that the context of a word can be changed. Is this right?
>
> 1) Yes. That is what e.g. BIND normally does for Rebol
> blocks. It replaces the words contained in the block by their
> counterparts bound to the specified context, if possible.
In this case I would say it a bit different: BIND uses the given word as
a human-readable-descriptor. The word has no meaning at all, it's just a
description for BIND that specifies what to search in the context where
the KNOWN-WORD is included and than replaces the descriptor with a word
that has the same descriptor (IIRC you call it the argument of a word)
as the specified one, the same context as KNOWN-WORD and things like the
value of the word etc. are than accessable.
> 2) No. You cannot change the context of a word without
> replacing the word. (You may ignore this, if it isn't
> understandable for you ATM)
I think I understand this now. The key-word here is REPLACE, the word
looks like the same but it's not. So can we say what is normaly known as
a variable and that is referenced by name in Rebol a variable has two
properties: A name and a context. Only this combination is a full
qualifier for a "variable".
> Only the context as whole can be freed.
Hmm... Isn't this now a bit different in semantics to what we said
before? We are talking about blocks as mixed-context-containers. Ok. We
have contexts as a collection ("block") of words that share the property
same-context but don't have any functional meaning (a context is just a
collection and not a sequence that can be evaluated). So blocks and
contexts are orthogonal.
So why can't a word be removed from a context? Imagine a context with
1000 words and only 1 is still in use. Than i have 999 words that are in
memory but not used. Does this explain the memory footprint of Rebol?
> If you have got at least one context word, you are (at least
> theoretically) able to get all words of the specified context using
> BIND.
But we can't query the context, right? I can't say something like:
foreach word get-context KNOWN-WORD [?? word]
> It might be a good start to colorize the code from the
> Computed Binding chapter of Contexts.html, what do you think?
Good idea! I think I'm going to write an other "words & context"
article: Words & Contexts for dummies or something like this. And using
colors to show the contexts is a very nice way :-)). Maybe you can alter
your stuff too.
> > I think I now know why: Because the words carry the context around,
> > ... you have a set of words with a lot of different contexts, which
> > are used in the actual block.
>
> That's it.
Well, fine. It takes some time but understanding all this is very
important to get the spirit of Rebol. I hope others learn as much as I
do. Robert
[13/23] from: robert:muench:robertmuench at: 20-Nov-2002 9:36
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 3>>
> Subject: [REBOL] Re: Binding
> I leave it to other to explain that code in more detail.
Hi, I do it for training :-))
> I wanted to provide some different examples of words and their
> bindings just in case they help in understanding. I recommend
> pasting the script below into the console.
Thanks a lot. Very good stuff!
> ; The following four lines when executead establish the
> ; word "greeting" into four different contexts.
Ok, so far I got it ;-)) BTW: As I'm still doing C++ programming and
switching brain between these two isn't smooth all the time I think of
CONTEXT of something like a namespace. The only hard part is that you
don't have to use fully qualified names in Rebol. So you don't see it.
> ; instances-of-greeting will contain four values
> ; of type word! all of which have the same name {greeting}
> ; but which differ in that each is bound to a different context.
Ok, that's clear too.
> ; Visually we might think it is the same word, but internally
> ; REBOL knows to keep them seperate.
Yep.
> expression: compose/deep [ rejoin [(instances-of-greeting)] ]
I have question here: How does the evaluation sequence look like? Will
compose/deep (a) evaluate instance-of-greeting and replace the parens
with the result or (b) keep a live reference to the different greeting
so that I even could change the value?
> ; But just because it looks like code doesn't mean we can't
> ; treat it as data.
;-) That's cool and I'm not used to it...
> ; We can make a function from the expression by using the
> ; expression as the function body.
Nice too.
> ; Or demonstrate how the words in a function body are bound
> ; to the function arguments.
This sounds logical but it's really tricky I think. This means that
EXPRESSION is switching clothes. I mean, if you think of the words as
pointers to some value, in C the pointers would stay the same. No matter
where you look at the pointes. In Rebol the pointers get new values
depending of the context ;-) you read them out. Pretty nice, but very
complex to understand and even more complex to keep track of.
> g: func [ greeting ] expression
> g "Yo"
>
> ; Which is like using BIND on the expression itself - lets
> bind it to ; the swedish context.
>
> new-expression: bind/copy expression in sweden 'self
> do new-expression
For GREETING it's now clear what happens. But what happens for REJOIN? I
mean this word isn't in the swedish context. So Rebol key-words must
somehow be marked so that BIND knowns to skip these. Is it this way?
> ; BIND changes the context of words in a block
Ok, to the context you specify through the KNOWN-WORD argument.
> so does FUNC to its body block.
And here, to what context are those words bound?
> CONTEXT (make object!) also changes the
> context of ; words in a block it is given. ; In this next
<<quoted lines omitted: 7>>
> ]
> get script/context/does/2
== "Dollar" because executed in the "global" context.
> ; Now see the change after the script block is evaluated.
>
> do script
> get script/context/does/2
Ok, and here the code is doing a name-lookup for "currency-name" and
finds this first definitio within the "euro-zone" context.
Thanks a lot for all these very helpful examples. Robert
[14/23] from: brett:codeconscious at: 20-Nov-2002 23:45
Hi Robert,
> > expression: compose/deep [ rejoin [(instances-of-greeting)] ]
>
> I have question here: How does the evaluation sequence look like? Will
> compose/deep (a) evaluate instance-of-greeting and replace the parens
> with the result or (b) keep a live reference to the different greeting
> so that I even could change the value?
I think (a). In my example, instance-of-greeting when evaluated results in a
block.
> > ; But just because it looks like code doesn't mean we can't
> > ; treat it as data.
>
> ;-) That's cool and I'm not used to it...
Oh good. ;^)
> > ; Or demonstrate how the words in a function body are bound
> > ; to the function arguments.
>
> This sounds logical but it's really tricky I think. This means that
> EXPRESSION is switching clothes.
Yes the wording is not good (I should have been in bed). I think Ladislav
and Gabriele explain it better.
> I mean, if you think of the words as
> pointers to some value, in C the pointers would stay the same. No matter
> where you look at the pointes. In Rebol the pointers get new values
> depending of the context ;-) you read them out. Pretty nice, but very
> complex to understand and even more complex to keep track of.
With much respect, thinking "of the words as pointers" is your concept :^)
Thinking in this way is making things complex to understand. When thinking
this way it *seems* that pointers get new value depending on the context.
But I believe REBOL does not have or need that idea.
In C a variable brings to mind a a memory location where some bits are
stored. I think there's even an operator or function that can get the actual
memory address when given a variable. Compiled languages do that.
In REBOL a word can be used to represent variable data but I think it is
*not* helpful to imagine it as a memory location - it a symbol for something
else.
Joel published an interesting link to an article on "Leaky Abstractions".
REBOL gives a nice strong abstraction, but we should not try too hard to
drill holes in it! :^)
> > g: func [ greeting ] expression
> > g "Yo"
<<quoted lines omitted: 7>>
> mean this word isn't in the swedish context. So Rebol key-words must
> somehow be marked so that BIND knowns to skip these. Is it this way?
Yes - the spelling of the words identifies them :^)
I think BIND parses the block. Each word it encouters it tries to find a
match in the supplied "known" context. If
it finds a word in the known context with the same spelling it will bind the
word it is working on to the "known" context.
Something like that :^)
When you load the script (paste it into the console) all the words start in
the global context (system/words). After the bind in the example has
finished all the GREETING words are modified [or replaced - ask Ladislav
:^) ] but REJOIN is left unchanged because it does not exist in the "known"
context.
> > ; BIND changes the context of words in a block
>
> Ok, to the context you specify through the KNOWN-WORD argument.
>
> > so does FUNC to its body block.
>
> And here, to what context are those words bound?
I think Ladislav in another post said that the context is created when the
function is evaluated.
> > CONTEXT (make object!) also changes the
> > context of ; words in a block it is given. ; In this next
<<quoted lines omitted: 15>>
> Ok, and here the code is doing a name-lookup for "currency-name" and
> finds this first definitio within the "euro-zone" context.
This line:
get script/context/does/2
is not dependent on what the code is doing. So there is no name-lookup for
currency-name
.
This bit:
script/context/does/2
results in the word "currency-name" in the context symbolised by euro-zone.
The GET then gets the value of this currency-name-in-the-euro-zone word.
In my mind, the currency-name-in-the-euro-zone word *is a different word
instance* to
the currency-name-in-the-global-context word. But that is just my mind :^)
> Thanks a lot for all these very helpful examples. Robert
You are very welcome.
Brett.
[15/23] from: lmecir:mbox:vol:cz at: 20-Nov-2002 13:30
Hi Robert,
> > Of course, you can collect sample words of some contexts and
> > check all words which context they are from.
>
> Yes, but I need to know about the context ;-)
It will work, if you try, just use words to "represent" contexts.
> > Sample context-creating functions: USE, MAKE (OBJECT! FUNCTION!),
> > REPEAT, FOREACH. Any function from the above list creates
> > exactly one context whenever it is evaluated.
>
> Is there a list of all functions that create contexts? IMO this would
> help a lot to understand all this.
I would say, that the list is almost complete. Any other function is a
derivative of a function from the above list, I think.
> > That is what e.g. BIND normally does for Rebol
> > blocks. It replaces the words contained in the block by their
<<quoted lines omitted: 6>>
> as the specified one, the same context as KNOWN-WORD and things like the
> value of the word etc. are than accessable.
We must take into account the fact, that BIND can either replace a word (if
there is a corresponding word in the target context), or leave it untouched
(if a corresponding word in the target context doesn't exist). In the latter
case the word cannot be just a "human readable descriptor".
> > 2) No. You cannot change the context of a word without
> > replacing the word. (You may ignore this, if it isn't
<<quoted lines omitted: 4>>
> properties: A name and a context. Only this combination is a full
> qualifier for a "variable".
Sounds good.
> > Only the context as whole can be freed.
> Hmm... Isn't this now a bit different in semantics to what we said
<<quoted lines omitted: 6>>
> 1000 words and only 1 is still in use. Than i have 999 words that are in
> memory but not used. Does this explain the memory footprint of Rebol?
Well, see this:
w: use [x y] ['x]
Do you think, that 'y got lost, because we didn't retain it? But it is still
accessible, as long as 'x is accessible, because if we can access one
context word, we are able to access them all:
block: reduce ['y bind 'y w] ; == [y y]
set block [1 2]
reduce block
> > If you have got at least one context word, you are (at least
> > theoretically) able to get all words of the specified context using
> > BIND.
>
> But we can't query the context, right? I can't say something like:
>
> foreach word get-context KNOWN-WORD [?? word]
Actually, we can, although there are some exceptions. See this:
do http://www.rebolforces.com/~ladislav/contexts.r
context-words: function [known-word [word!]] [result] [
result: make block! 0
if unbound? known-word [return first system/words]
foreach word first system/words [
if not same? word bind word known-word [
append result word
]
]
result
]
Now we can:
foreach word context-words known-word [?? word]
-L
[16/23] from: otherchaz:mindspring at: 20-Nov-2002 6:23
> ; The following four lines when executead establish the
> ; word "greeting" into four different contexts.
<<quoted lines omitted: 11>>
> in sweden 'greeting
> ]
;so now we can pick random instances
;which all appear to be the same
h: func [][pick instances-of-greeting random 4]
i: h
j: h
k: h
l: h
;but they are randomly different
get i
get j
get k
get l
;for instance one possible outcome is
; >> get i
; == "Salut!"
; >> get j
; == "Hi!"
; >> get k
; == "Hey!"
; >> get l
; == "Salut!"
; run these functions of Ladislav Mecir
undefined?: func [
{determines, if a word is undefined}
word [any-word!]
] [
error? try [error? get/any :word]
]
s-c?: func [
{Are word1 and word2 bound to the same context?}
word1 [word!]
word2 [word!]
] [
found? any [
all [
undefined? word1
undefined? word2
]
all [
not undefined? word2
same? word1 bind use reduce [word1] reduce [
'first reduce [word1]
] word2
]
]
]
; define this block
languages: ["usa" "australia" "france" "sweden"]
;Why doesn't this return which language the greeting is in?
m: func [instance] [for index 1 4 1 [if s-c? [instance pick
instances-of-greeting index] pick languages index] ]
m i
C
[17/23] from: g:santilli:tiscalinet:it at: 20-Nov-2002 15:11
Hi Carl,
On Wednesday, November 20, 2002, 1:06:13 AM, you wrote:
CaR> BTW, named contexts *are* created by MAKE OBJECT... what you want is a way to
CaR> pass them as an argument to BIND (rather than a word from the object). An
CaR> interesting
CaR> (and doable) idea.
Either that, or making IN accept a block too. :-)
in object [a b c]
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[18/23] from: brett:codeconscious at: 21-Nov-2002 11:42
> ;Why doesn't this return which language the greeting is in?
>
> m: func [instance] [for index 1 4 1 [if s-c? [instance pick
> instances-of-greeting index] pick languages index] ]
>
> m i
There are some coding errors in this. The the brackets are around the IF
condition instead of the body block of the IF. Also, once the IF condition
becomes true you should RETURN the result immediately rather than continuing
the search. If you don't use the RETURN function then the code would return
the result of the IF when index = 4, if there was a match you get right the
result, if there was no match then you would get NONE.
Finally you need to pass the M function one of these word instances.
If changed your code as described:
m: func [instance] [
for index 1 4 1 [
if s-c? instance pick instances-of-greeting index [
return pick languages index
]
]
]
m 'greeting
a-greeting-word: in france 'greeting
m a-greeting-word
Regards,
Brett.
[19/23] from: lmecir:mbox:vol:cz at: 21-Nov-2002 22:17
Hi all,
I just modified http://www.rebolforces.com/~ladislav/contexts.html
, where I used a colorization technique to discern contexts.
-L
[20/23] from: robert:muench:robertmuench at: 22-Nov-2002 10:44
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 4>>
> I just modified http://www.rebolforces.com/~ladislav/contexts.html
> , where I used a colorization technique to discern contexts.
Hi, great but I see only one red line. Is this all? Robert
[21/23] from: lmecir:mbox:vol:cz at: 22-Nov-2002 11:54
> Hi, great but I see only one red line. Is this all? Robert
I colorized only the computed binding example. It should contain an (almost)
red line - all words unbound, then a black line - all words global, next a
line containing black and green words (global and use1 words) and finally a
line containing black, green and one blue (global, use1 and use2) word.
I checked that with Explorer, Konqueror and Mozilla, and it seemed to work.
If you see something different, it is strange. Could you (eventually)
suggest what change should I make to achieve the same result in your
browser?
TIA
-L
[22/23] from: robert:muench:robertmuench at: 22-Nov-2002 13:46
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 9>>
> I checked that with Explorer, Konqueror and Mozilla, and it
> seemed to work.
Hi, I'm using Opera and yes the colors are there. The green words can't
be distinguished from the black one (or at least it's hard for me) on a
white background. I would change the background color.
One comment to the whole article: The first time binding is mentioned is
at the end of section 5. But you don't explain what it is, why we have
it etc. Then section 7 starts with binding but I still don't know what
it is. So it just falls from heaven... Howabout adding the nice examples
from Brett? Your stuff is very good but I'm not sure if everyone can
follow it and see what it's good for. Robert
[23/23] from: lmecir:mbox:vol:cz at: 22-Nov-2002 16:53
Hi, I changed the colours a bit, hope it will be better.
-L
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted