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

[REBOL] Context Stuff Re:

From: bhandley:zip:au at: 1-Aug-2000 11:13

> Ok, I have been trying to understand this context stuff. > I created a function and have a "word" within a while function > embedded within. The problem is that the function does everything I want > the first time.
A lot of people would like their code to work first time ;)
> However the "word" within the while function continues to > hold the last value. I can do a source on the function and see the last > value within. How can I have the function return the string value to > nothing at the end of exection.
Since I tripped over this myself, and others helped me, it's my turn. my-func1: func [] [ ; blk-in-function-definition will refer directly to a block that is stored as part of the function definition blk-in-function-definition: [] append blk-in-function-definition "x" blk-in-function-definition ] my-func2: func [] [ ; new-blk-each-call will refer to a block that is created each time the function is evaluated new-blk-each-call: make block! 1 ; Creates a fresh block another way is use copy [] append new-blk-each-call "x" new-blk-each-call ] I've attached a message by Brian Hawley showing how this behaviour can be put to good use. Brett. ------------ Hi Brett! While you're reassembling, think of the advantages that this trick can give you. This kind of assignment can be useful for implementing what the C world calls static local variables. You can set a word to a literal string value, then append to that string to create a string accumulator. This allows you to build a string incrementally. You can set a word to a literal block and store values in it. This allows you to use a function like a Scheme closure, a function with values bundled in it, like OOP in reverse. This technique allows OOP-like programming with better control of your data because it is hidden inside the function. Look at for an example of how this technique can make for bulletproof code. The most fun with this technique comes when you use compose to create your code blocks. For example, consider this: f: func [key] [ table: make hash! [a "a" b "b"] table/:key ] Trivial, true, but imagine that pattern with a much larger hash table, or a large binary value, or a dozen charsets for a parse process. You can't directly represent those values as literals - they get recreated every time. Do that in a function and the function gets really slow. But do this: f: func [key] compose [ table: (make hash! [a "a" b "b"]) table/:key ] and the hash table is only created once, right before the function is created. All calls to f then reference the now literal hash table, making for a very fast, memory efficient function. If you can use literal hash tables in a function, you can do one of the coolest tricks from the functional-language world, memoization. When you memoize a function, it remembers the results of the calls to the function, so that later calls of that value don't have to recalculate the result. You can even do this from the outside with a separate function, although REBOL's flexible args make the general case of that rather tricky (I'll work on it). Here's a one-arg memoize function: memoize: func ["One-arg memoize, kinda weak :(" 'f [word!]] [ set f func [x /local f saved res] compose [ f: (get f) saved: (make hash! []) either res: select saved :x [first res] [ res: f x append saved reduce [:x reduce [res]] res ] ] ] I know, it looks awkward, but this can speed up functions that have to go through even worse trouble to calculate their values in the first place. It also helps with those that use deep self-recursion to calculate their values, as REBOL's stack space is quite limited. Fun stuff? Brian Hawley [bhandey--zip--com] wrote: