Frank Sievert ([EMAIL PROTECTED]) wrote:
>Is there a way to get the words of the context of a function?

Not directly.

>Example:
>    f: func [a] []
>    g: func [a] [print a]
>
>Does anyone know a way to change function f AFTER its definition
>in that way, that it will work like function g?

f: :g

>The following does not work:
>   insert second :f reduce ['print first first :f]
>
>Because the first (and third) of a function is not bound to
>the functions context.
>
>I think there is no direct way to get the word with binding,
>I could only get the words out of functions body :(

During the REBOL 2 development process REBOL was changed to
specifically prohibit that kind of access. This was done to
keep the interpreter from crashing. It's a bad idea to do
this kind of thing, as it leads to completely unstable code.

>I am working at a serialize script, which also serializes
>contexts etc.

The contexts of functions are not properly persistent. While
REBOL does save a context for each function, it only does so
for the purpose of reuse. The values of the words in that
context are trounced with every call to the function.

If you want to write solid code in REBOL, you should pretend
that the function contexts are completely volatile between
calls, even if the current implementation makes this not so
on some occasions. The only persistent contexts you need to
concern yourself with are object contexts. If you serialize
any more contexts than that, people who use your code might
try to depend on persistence of contexts between sessions
that aren't even persistent within the same session.

If you want to use persistent values within the context of
a function (like static variables in C), use the technique
of embedding series or object values in the code block of
the function.

Do you remember the recurring discussions that begin with
someone new to REBOL getting tripped up because they did
   a: []
in function code, expecting it to behave like
   a: copy []
instead? Someone always calls this a bug in the language
design, but used properly it can be one of REBOL's most
powerful features.

For example, try this:

     f: func [x /local a] [
         a: [] append/only a x foreach x a [print x]
     ]

This code depends on the block embedded in the function
being modified by the function, and having those changes
be persistent. All you would need to save here would be
the spec and code blocks of the function to be saved -
it doesn't depend on the context being persistent, which
is good because function contexts effectively aren't.

This same technique can be used with values that aren't
directly representable as literals, such as hashes, lists,
bitsets, functions and objects, if you create the function
code block with some function like compose.

For example, in this function:

     alphanum?: func [s /local alphanum] compose [
         alphanum: (
             charset [#"a" - #"z" #"A" - #"Z" #"0" - #"9"]
         ) parse/all s [some alphanum]
     ]

..., the function charset is only called once, before the
function alphanum? is created. The local variable alphanum
is assigned to the now literal bitset value embedded in the
code of the function, rather than being recreated every time
the function is called, an expensive process.

You can use this technique to speed up functions that parse
using local character sets, to index using local hashes, to
create local functions without having to recreate them at
each call - basically anywhere you need to hide persistent
values from uncontrolled modification. If you are used to
programming in the functional style, with closures, this is
how to have persistent data.

Of course, none of this will be needed when Carl gets done
with REBOL modules. When that happens you will be able to
use modules for all of your information-control needs and
you won't need to do these more arcane closure-type hacks.

Brian Hawley

Reply via email to