[REBOL] Re: [understanding 'bind]
From: rotenca:telvia:it at: 7-Mar-2002 17:40
Hi, Pat
Object creation in Rebol it is a little "strange". The first times i looked at
Rebol, I read the collowing code:
make object! [
a: 1
]
like: "create an object and set its field 'a at 1".
Today I read the code in another mode:
1) create a new context with the word 'a and the word 'self
2) assign to the value of 'self in this new context a pointer
to a representation of the new context (an object! datataype)
3) bind the user block to the new context
4) evaluate the user block
5) return the value of the local word 'self
There is little difference between an use block and an object creation:
use [a] [
a: 1
]
can be read:
1) create a new context with the word 'a ()
2) ()
3) bind the user block to the new context
4) evaluate the user block
5) return the (result of the evaluation)
I've put some parens to signal the where are changes. As you can see, the
changes are for the local 'self and the result, but both 'use and 'make
object! do 3 things:
1) create a context
2) bind a block to it
3) evaluate the binded block
'bind simply overrides the value of the words in the block with the value of
the words in the local context. If a word is not defined in the local context,
it conserve its previous context (if any) and its previous value (if any).
To be more precise: 'bind discards the old word and put in your block a new
word, bound to the new context.
A word cannot be changed at all. It is like 10. You can put 2 where one time
there was 10, but you can't change 10 to make it 2.
Also set-words cannot be changed at all:
a: 6
does not means:
"change the value of a"
it means:
"change the value which the context of 'a assigns to the symbol 'a"
'Set changes the context not the word.
One consequence is that you can pass a word from a block of code to another
without changing its binding. In other words: you can use a word of another
context in the "actual" one.
The function behaviour is a little different:
func [a][a: 1]
can be read:
1) create a local context with the word 'a ()
2) ()
3) bind the user block to the new context
4) ()
5) return (a pointer to the function code)
The binded block is NOT immediately evaluated, it will be evaluated only when
the 'func result (the function! datatype) will be evaluated. There are others
differences, like the args stuff, the default value of local words (=none!
instead of unset!) but for the binding it is all. We can think to a function
like a delayed 'use block: the evaluation - not the bind - is delayed.
Now to your code:
> o: make object! [
> print: func [b [block!]][rebol/words/print compose ["o-print-> " (b)]]
> test1: does [print ["test"]]
> test2: func [b [block!]][do b]
> test3: func [b [block!]][do bind b 'self]
> ]
>
> o/test1
> o/test2 [print ["Hello World!"]]
> o/test3 [print ["Hello World!"]]
In the object 'o appears the set-word print:, it becomes a word of the new
local context.
Every occurrence of the word 'print in the body block will be bound to the
local context: that 'print in test1 will become a local word. Then Rebol
evaluates the code of the object block, which creates the function test1. Its
body is binded the the local context of the function, which in this case does
not contain the word 'print, the word print is unchanged and remain bound to
the previous context (the object context).
When you invoke o/test1, will be evaluated the word 'print, bound to the
object context.
When you invoke o/text2, with the block [print ["Hello World!"]], the word
'print in this block is by default bound to the global context. The funtion
test2 executes this block without any changes, so the value of 'print will be
the same of the global 'print.
The funtion test3, instead, binds this block the object context (addressed
with 'self); this context contains the word 'print, so the value of 'print
changes and becomes the same of the local function 'print.
Hope this help.
---
Ciao
Romano