[REBOL] WYSIWYG programming (was: Block Creation)
From: lmecir:geocities at: 25-Oct-2000 3:05
This is for the people, who feel certain discomfort seeing some "surprising
once, surprising always" effects. I am trying to demonstrate for them (and
for myself) that:
1) They are right when they are telling: "There must be something wrong with
it."
2) How should we write our code to feel comfortable.
Part #1
Let's start with an example:
code1: [
i: 0
while [(i: i + 1) <= 5] [
block: []
insert block "text"
]
block
]
do code1
== ["text" "text" "text" "text" "text"]
Allow me to label the behaviour of Code1 as *strange*.
Now a second example:
code2: [
i: 0
block: copy []
while [(i: i + 1) <= 5] [
insert block "text"
]
block
]
do code2
== ["text" "text" "text" "text" "text"]
I would label this behaviour as *normal*.
What is wrong with Code1? Code1, as opposed to Code2 changed during its
execution! Let's see:
probe code1
[
i: 0
while [(i: i + 1) <= 5] [
block: ["text" "text" "text" "text" "text"]
insert block "text"
]
block
]
Conclusion: Code1 is not What You See Is What You Get Code. (Any
suggestions, how to call such code? I have got: What You See Is Not What You
Get Code, (Pure) Self Modifying Code, an analogy to Vivisection came to my
mind,...)
As we saw, copying can improve the behaviour of code WRT WYSIWYG properties
sometimes. An experiment:
code3: [
i: 0
while [(i: i + 1) <= 5] [
block: []
insert block "text"
]
block
]
do copy/deep code3
== ["text" "text" "text" "text" "text"]
probe code3
[
i: 0
while [(i: i + 1) <= 5] [
block: []
insert block "text"
]
block
]
Here it looks, that Code3 is now OK, because it didn't modify itself. What
went wrong? The problem is, that the deep copy of Code3 modified itself
during its execution! (You can easily prove that, if you store the copy in a
variable for future reference.) I think, that this example deserves the same
name as above.
Now a more advanced example (courtesy of Joel Neely):
code4: [
for test1 1 5 1 [
block: []
insert block "text"
]
block
]
do code4
== ["text" "text" "text" "text" "text"]
probe code4
[
for test1 1 5 1 [
block: []
insert block "text"
]
block
]
Here again, Code4 looks OK, because it didn't change. What went wrong? The
code *is* Self Modifying similarly as Code3. When we look at the code, we
see, that For is executed. As everybody suspects, For has to execute the
supplied body somehow. Instead of executing it directly it creates a Do-body
function. What is modifying itself during the execution is the Do-body
function, which uses a *deep copy* (See the similarity with Code3?) of the
supplied body, which means, that the supplied body will not be modified.
source for
for: func [
"Repeats a block over a range of values."
[catch throw]
'word [word!] "Variable to hold current value"
start [number! series! money! time! date! char!] "Starting value"
end [number! series! money! time! date! char!] "Ending value"
bump [number! money! time! char!] "Amount to skip each time"
body [block!] "Block to evaluate"
/local result do-body op
][
if (type? start) <> (type? end) [
throw make error! reduce ['script 'expect-arg 'for 'end type? start]
]
do-body: func reduce [[throw] word] body
op: :greater-or-equal?
either series? start [
if not same? head start head end [
throw make error! reduce ['script 'invalid-arg end]
]
if (negative? bump) [op: :lesser?]
while [op index? end index? start] [
set/any 'result do-body start
start: skip start bump
]
if (negative? bump) [set/any 'result do-body start]
] [
if (negative? bump) [op: :lesser-or-equal?]
while [op end start] [
set/any 'result do-body start
start: start + bump
]
]
get/any 'result
]
Another example showing what is wrong with the Self Modifying Code:
a: [append a [+ 1] 1]
>> do a
== 1
>> do a
== 2
>> do a
== 3
>> do a
== 4
>> do a
== 5
>> do a
== 6
>> do a
== 8
Although it seems like a bug, this example just demonstrates, that the
result of a Self Modifying Code cannot be "forecasted" without the detailed
knowledge of the implementation. Another example of this kind:
code6: [1 (remove code6) 2]
do code6
== [(remove code6) 2]
As well as this we might have expected 2 to be the result.
In the next part I am going to show you some less usual examples of Self
Modifying Code.
-Ladislav