WYSIWYG programming (was: Block Creation)
[1/7] from: lmecir:geocities at: 25-Oct-2000 2:54
Hello list,
I decided to write this, because I feel, that there is still a room for a
totally different description of What Is Going On and What Shall We Do.
code1: [
i: 0
while [(i: i + 1) <= 5] [
block: []
insert block "text"
]
block
]
; Let's look at the result:
do code1
*Every* newcomer labels the behaviour of Code1 as strange. Why? The reason
is not the surprise, that Block
[2/7] 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
[3/7] from: holger:rebol at: 30-Oct-2000 9:32
On Wed, Oct 25, 2000 at 03:05:21AM +0200, Ladislav Mecir wrote:
> Another example showing what is wrong with the Self Modifying Code:
>
> a: [append a [+ 1] 1]
The above expression modifies a block while it is being evaluated. AFAICT at
this time the result of such an operation should be considered "undefined" and
implementation-dependent
. In other words: don't do that ! I don't think the
behavior can be called a bug as long as no specs have been defined for how
the language should behave in this case.
Most languages have expressions which are well-formed within the language, yet
have unspecified semantics. An example is something like
a: (*p++)+(*p++)
in C. Here it is undefined whether the second access to "p" occurs before or
after incrementing it for the first time (assuming I remember the C specs
correctly...)
A "legal" way to rewrite the above REBOL expression would, e.g., be:
a: [append last a [+ 1] do [1]]
This way the main block does not get changed during evaluation. Only the
block referenced from the main block (the one initialized to be [1]) gets
changed. That is completely legal.
I hope you can see now why I dislike the term "self-modifying code". There is
conceptually a huge difference between the first and second example, and
the term "self-modifying code" tries to be a catch-all phrase that encompasses
(and discourages) within the same category both legal (and potentially useful)
and illegal practices.
--
Holger Kruse
[holger--rebol--com]
[4/7] from: jeff:rebol at: 30-Oct-2000 8:39
Howdy, Holger:
> Most languages have expressions which are well-formed
> within the language, yet have unspecified semantics. An
> example is something like
>
> a: (*p++)+(*p++)
>
> in C. Here it is undefined
You bet it's undefined. What are you gunna do: goto the
label a;? ;-)
-jeff
[5/7] from: holger:rebol at: 30-Oct-2000 10:00
On Mon, Oct 30, 2000 at 08:39:45AM -0800, [jeff--rebol--net] wrote:
> Howdy, Holger:
> > Most languages have expressions which are well-formed
<<quoted lines omitted: 6>>
> You bet it's undefined. What are you gunna do: goto the
> label a;? ;-)
Argl... Too much REBOL. I see colons everywhere :).
a=(*p++)+(*p++);
--
Holger Kruse
[holger--rebol--com]
[6/7] from: lmecir:geocities at: 30-Oct-2000 19:44
Hi Holger,
I am glad I provoked this nice discussion! My point was *very* similar to
yours. I wanted to suggest everyone to prefer the use of (at least
relatively) WYSIWYG code, defined as follows:
a) I call a Rebol value a Self Modifying (Rebol Code), if its evaluation
(with a help of Do e.g.) causes its change (to be precise, I should define
what is a Change, but let's leave that for a future discussion). (This
definition differs from a "usual" definition of a Self Modifying Code!)
b) I call a Rebol value a WYSIWYG (Rebol Code), if its evaluation (using Do
e.g.) doesn't cause an evaluation of a Self Modifying Rebol Code.
c) There are some Rebol values, like functions/natives If, Either, For,
While, Make, ..., for whose the latter depends on the argument(s) they
receive or on some other unknowns. Such values I call (relatively) WYSIWYG.
See a more complete Message-ID: <005801c041bb$902f90a0$[497114d4--LadislavMe]>.
Regards
Ladislav
[7/7] from: chaz:innocent at: 30-Oct-2000 20:51
I'm also glad you provoked this nice discussion. I always enjoy it when RT
staff can be teased out their cubicles and into the lists. Haven't seen
Holger for a while - thanks to you and Joe tag-teaming him, now we see him
nearly every day!
chaz
At 07:44 PM 10/30/00 +0100, you wrote:
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted