[REBOL] Words, Bindings and Contexts. (8)
From: lmecir:geocities at: 29-Jul-2000 9:56
The last part was about the behaviour of Rebol Functions. The
present behaviour can be called "Computed Quasi Static Binding
with Dynamic Recursion Patch."
Interesting about the "Computed Quasi Static Binding" is, that it
can handle recursion even without the "Dynamic Recursion Patch",
as can be
seen in the next model:
; Model of Context creation:
; **************************
make-context: func [
{create a Context containing given Words}
words [block!]
/local context-init result
] [
; this implementation has got an issue:
; the created Context always contains 'Self
words: difference/only words [self]
context-init: make block! 4 * length? words
foreach word words [
append context-init to set-word! word
append context-init none
append context-init :unset
append context-init to lit-word! word
]
result: make object! context-init
unset in result 'self
result
]
{
The following version of Same-context? uses Make-context to
look more natural:
}
same-context?: func [
{find out, if the given Words are the Words of the same
Context}
word1 [word!]
word2 [word!]
] [
either special-context? word2 [
special-context? word1
] [
same? word1 bind in make-context reduce [word1] word1
word2
]
]
; Model of CQSB function:
; *****************************
cqsb-function!: make object! [
; every cqsb function has got a Spec attribute
spec: none
; every cqsb function has got a Body attribute
body: none
]
; Model of CQSB Func function:
; *********************************
cqsb-func: func [
{create a CQSB-function!}
spec [block!]
body [block!]
/local spec-too body-too
] [
spec-too: copy spec
body-too: copy/deep body
make cqsb-function! [
spec: spec-too
body: body-too
]
]
; Model of the CQSB function body execution:
; *******************************************
; the same as for Sim-function
do-body: func [body] [do body]
; Model of CQSB function Evaluation:
; ***********************************
cqsb-evaluate: func [
{evaluate a sim-function contained in a block with its
arguments}
block [block!]
/local cqsb-f new-context actual-values
] [
; evaluate the arguments
block: reduce block
; the executed cqsb-function is first
cqsb-f: first block
; create a new Context
new-context: make-context cqsb-f/spec
; give new Context words the supplied values
set/any bind/copy cqsb-f/spec in new-context 'self next block
; execute the function body and return the result
return do-body bind/copy cqsb-f/body in new-context 'self
]
; Some tests:
; **************
blk: copy []
probeblk: func [] [
prin mold blk
prin ": "
print mold reduce blk
]
recfun: cqsb-func [x] [
append blk 'x
either x <= 1 [
probeblk
] [
cqsb-evaluate [recfun x - 1]
]
]
cqsb-evaluate [recfun 3]
probeblk
{
Results:
>> cqsb-evaluate [recfun 3]
[x x x]: [3 2 1]
>> probeblk
[x x x]: [3 2 1]
This shows, that "Pure CQSB" looks better than "CQSB with DRP".
Recursion is not the only case, where "Pure CQSB" looks better.
For another example, see this:
}
f: func [x] ['x]
y: f 1
z: f 2
get y
{
Results:
>> get y
== 2
While Pure CQSB yields:
}
f: cqsb-func [x] ['x]
y: cqsb-evaluate [f 1]
z: cqsb-evaluate [f 2]
get y
{
and the results:
>> get y
== 1
But, as always, everything has got its price. Pure CQSB is more
demanding (every call needs a new Context/Binding). Moreover, the
above implementation is not GC-bug proof.
}
to be continued...