[EMAIL PROTECTED] wrote:
>
> Hi Elan.
> > Hi Russell,
> > The function:
> > >> f: func [/local a] [a: "" insert a 1 a]
...
>
> But I must admit I'm "flabbergasted" at how the function 'f as defined
> immediately above, works on repeated
> applications...
>
> It appears that the interpreter is modifying the source!
>
This is another example of confusion caused by unfortunate terminology
in REBOL. (It took me a LOOOONG time to figure this one out, which
occurred in the course of the "series" discussion we've been having.)
The REBOL mezzanine function 'source should have been named something
like 'pretty-print instead (ring any bells for you old LISP hackers?)
Consider:
>> flarp: [a: "" append a "?" print a]
== [a: "" append a "?" print a]
>> type? flarp
== block!
>> foreach item flarp [print [type? :item "^-" :item]]
set-word a
string
word append
word a
string ?
word print
word a
>> source flarp
flarp: [a: "" append a "?" print a]
Our conventional model of programming is that programs are written in
"source code" which is compiled into "object code" which can be
executed by a computer. In this model, changing the "object code" is
usually SEVERELY frowned on, as the program then exhibits behavior
which cannot be inferred from reading the "source code".
REBOL doesn't work that way.
'flarp is set to a value which is simply [some internal representation
of] a block. We can iterate through the elements of that block, just
as with any other block. Saying {source flarp} is NOT asking for
some "object code" to be "decompiled" into "source code" in the con-
ventional sense of those terms, but simply asking for the content
of the content to be displayed as text.
>> x: 23
== 23
>> source x
x: 23
Even thought the number twenty-three is represented in binary inside
the system, asking for it to be displayed as text isn't really
decompiling; it's just another form of printing.
NOW consider:
>> bletch: func [/local a] flarp
>> bletch
?
>> bletch
??
>> bletch
???
which left me VERY confused the first time I encountered it. Why
is the local variable 'a GROWING even though the body of 'flarp
clearly shows it being initialized to ""????
What happens is simple, but non-intuitive (therefore worthy of an
explicit description in REBOL documentation) for those of us who
already program in other languages. The description also SOUNDS
complicated, but I now believe that is just because we don't have
a good vocabulary for discussing it.
'func creates a 'function! whose "code" is a COPY of the block
that is the last argument to 'func. It isn't object code, it's
just a block. So:
>> bletch: func [/local a] flarp
>> mold second get 'bletch
== {[a: "" append a "?" print a]}
>> second get 'bletch
== [a: "" append a "?" print a]
Let me use the name <<BODY>> (intended to make clear that it is
a name for this discussion only, and not legitimate REBOL
notation) to refer to this block. The second element in <<BODY>>
is a string (therefore a series) of length zero.
When we say:
>> bletch
?
we cause <<BODY>> to be interpreted. The first element is a
'set-word! which causes the local variable a to be made to refer
to a string. The word 'a is set to refer to THE SECOND ELEMENT
OF <<BODY>> ITSELF! Therefore, the {append a "?"} glues a question
mark character onto the end of the second element of <<BODY>>.
Finally, {print a} evaluates 'a (which refers to the second element
of <<BODY>>) and prints the result -- a single question mark.
However, as a result of the 'append, the second element of <<BODY>>
HAS BEEN MODIFIED, and now is "?". Therefore, when we invoke
'bletch again:
1) the set operation {a: ...} makes 'a refer to the second element
of <<BODY>> (which is now "?")
2) the referent of 'a has a "?" tacked onto the end (making the
second element of <<BODY>> now be "??")
3) the result of evaluating 'a is printed, displaying "??" to
the console.
Therefore, pretty-printing 'bletch (via the misleadingly-named word
'source) also shows the results of modifying the second element of
<<BODY>>, as in:
>> source bletch
bletch: func [/local a][a: "??" append a "?" print a]
>> second get 'bletch
== [a: "??" append a "?" print a]
That 'func made a copy of its last argument ('flarp, above) can be
demonstrated by:
>> source flarp
flarp: [a: "" append a "?" print a]
As with (early implementations, at least) of LISP before it, REBOL
refuses to make our conventional distinctions between data and code.
The body of a function is just a block, and therefore subject to
anything else we may do to a block, as in:
>> glop: second get 'bletch
== [a: "??" append a "?" print a]
>> glop/2: "OK"
== [a: "OK" append a "?" print a]
>> bletch
OK?
-jn-