Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] context of a function Re:

From: brian:hawley:bigfoot at: 18-Aug-2000 20:54

Frank Sievert ([fsievert--uos--de]) 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