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

[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