[REBOL] WYSIWYG programming
From: lmecir:geocities at: 25-Oct-2000 12:22
Part #2
Use as a code modifying function:
---------------------------------
original-code7: [
temporary: "temporary"
]
code7: copy original-code7
use [temporary] code7
same? first original-code7 first code7
== false
You can say: "So what? The Use behaviour is normal!" The problem is, that
you can unintentionally write a Self Modifying Code with all its
disadvantages, as the next code shows:
f7: func [level] [
use [temporary] [
if level = 0 [
temporary: "temporary"
f7 level + 1
print ["Temporary:" temporary]
]
]
]
f7 0
** Script Error: temporary has no value.
** Where: temporary
Is there a way out? Yes there is, quite simple:
f8: func [level] [
use [temporary] copy/deep [
if level = 0 [
temporary: "temporary"
f8 level + 1
print ["Temporary:" temporary]
]
]
]
f8 0
Temporary: temporary
*The WYSIWYG rule*: If you use a modifying function don't allow it to modify
the executed code, supply it a code copy instead.
Another way to cope with the above trouble is to create a non-modifying Use,
e.g. like this:
orig-use: :use
use: func [
"Defines words local to a block."
words [block! word!] "Local word(s) to the block"
body [block!] "Block to evaluate"
] [
orig-use words copy/deep body
]
Make as a code modifying function:
-----------------------------------
f9: func [level] [
make object! [
a: 2 * level
b: either zero? level [
f9 1
] [
none
]
a: a + 1
]
]
probe f9 0
make object! [
a: 0
b: unset
]
Once again, Make modified its second argument, which happened to be the code
in execution. The way out is easy:
f10: func [level] [
make object! copy/deep [
a: 2 * level
b: either zero? level [
f10 1
] [
none
]
a: a + 1
]
]
probe f10 0
make object! [
a: 1
b:
make object! [
a: 3
b: none
]
]
Repeat as a code modifying function:
-------------------------------------
Let's try a more complicated example. In the Set Theory the sets modelling
integer numbers 0,1,2,3,... are created as follows:
0 is modelled by empty set, which is normally denoted by 0 too
every other number is modelled as the set containing all models of integers
smaller than the modelled integer, i.e.
1 is modelled by [0]
2 is modelled by [0 [0]]
3 is modelled by [0 [0] [0 [0]]]
...
A Rebol function to do this could be written as:
f11: function [n] [result] [
if n = 0 [
return 0
]
result: copy []
repeat i n copy/deep [
append/only result f11 i - 1
]
]
>> f11 0
== 0
>> f11 1
== [0]
>> f11 2
== [0 [0]]
>> f11 3
== [0 [0] [0 [0]]]
>> f11 4
== [0 [0] [0 [0]] [0 [0] [0 [0]]]]
>> f11 5
== [0 [0] [0 [0]] [0 [0] [0 [0]]] [0 [0] [0 [0]] [0 [0] [0 [0]]]]]
What would happen, if we allowed Repeat to modify the executed code? Let's
see:
f12: function [n] [result] [
if n = 0 [
return 0
]
result: copy []
repeat i n [
append/only result f12 i - 1
]
]
>> f12 0
== 0
>> f12 1
== [0]
>> f12 2
== [0 [0]]
>> f12 3
== [0 [0] [0]]
Forskip is a Modifying Function too.
Next part will contain more WYSIWYG examples.
-Ladislav