One step closer to closures, or, how I captured variables by clever use of context switches.

Andre Garzia andre at andregarzia.com
Fri Aug 29 16:17:45 EDT 2008


Randall,

the problem is always a performance one. Revolution is extremely fast,
I really think it is powered by some alien technology. I've just
deployed a code that has so many nested loops that makes your head
hurt and yet it runs millisecs. A message like the one we're talking
would be called ALL TIME, Revolution is always changing stuff, so the
best would be to tag certain changes as observable changes not to
impact performance. As an example, just launch the message watcher,
select all messages and move the mouse around, the sheers quantity of
messages and how fast they are processed is amazing.

If you liked the idea of runtime code generation, side effects and
capturing things from other contexts, you might like learning more
about Lisp. It's a very fun and enlighting language, not Desktop
oriented (or even application-delivery oriented), I have the feeling
that learning more about Lisp makes me a better programmer in Rev. I
am reading some nice books where the language is the least important
thing, the real important thing is how to think and solve problems.

You might like:
Structure and Interpretation of Computer Programs (Also known as SICP,
available for free online and even in video format)
Thinking Forth (Also available for Free)

Cheers
andre



On Fri, Aug 29, 2008 at 2:14 PM, Randall Reetz <randall at randallreetz.com> wrote:
> Cool!  What i havw always argued for is a global property that turned on or off the behavior that the changing of any var or property generated a message.  The message would only happen if a property "sharechanges" of all vars and props (by default false) was set to true. The message would be sent with context and old value parameters.
>
> on rect_changed, context, oldval
>  Storecontexthistory
>  Bla bla bla
> End rect_changed
>
> randall
> -----Original Message-----
> From: "Andre Garzia" <andre at andregarzia.com>
> To: "How to use Revolution" <use-revolution at lists.runrev.com>
> Sent: 8/29/2008 1:55 AM
> Subject: One step closer to closures, or,       how I captured variables by clever use of context switches.
>
> Folks,
>
> This is the kind of post you get when I keep code until 5:15 AM. Today
> I've set a goal to produce a library that would allow me to create
> persistent variables, by persistent variables I mean that when the
> program finishes it somehow saves the variable contents and when it
> loads, it inserts the content back. I know about custom properties,
> SQL Databases, stack files, that's how we usually solve this kind of
> issue, but I'd decided to try something different and work with actual
> variables.
>
> To solve this problem, I've decomposed the task into two big
> components, the saver and the loader. The loader is the piece of code
> that picks the value and inserts back into the variable, this is
> trivial, you just read the value from somewhere and insert it back,
> the tricky thing is the saver.
>
> Picking values from global variables is easy, you just declare a
> global and grab the value. Script local variables are easy to access
> when you're in the same script. Temporary variables, well, those are
> tricky to grab when you're not in the same handler as them. So the big
> task is, how to we access variables that were defined and used in a
> different context? For those new to transcript let me put a simple
> example below:
>
> on firstHandler
>  local temp
>  put "I am a happy variable" into temp
> end firstHandler
>
> No code outside "firstHandler" can query the value of the temp
> variable, it is defined in the context of that handler. Now, imagine
> that you have the following piece:
>
> on firstHandler
>  local temp
>  put "I am a happy variable" into temp
>  newPersistentVariable "temp"
>  put "I've just changed the value of temp." into temp
>  secondHandler
> end firstHandler
>
> on secondHandler
>  put captureVariable("temp")
> end secondHandler
>
> And when secondHandler runs, it outputs "I've just changed the value
> of temp.". If you look carefully at the code above, you'll see that
> this is not an easy task. We have a strange handler called
> newPersistentVariable which we don't know what it is and on the
> secondHandler we have a function that is supposed to return the value
> from a variable on the other handler.
>
> Now, even without the details about those two functions, you can see
> that we're redefining the content of the temp variable after calling
> newPersistentVariable, so in a magic way, captureVariable function is
> returning the last value of temp .
>
> How does it works? It works by capturing the context and switching to
> it when needed. When newPersistentVariable is called it receives a
> param which is the variable name that you want to keep track (not it's
> value). newPersistentVariable then checks the executioncontexts and
> save it for later reference. When we call captureVariable()  we pass
> it a variable name, it then checks to see in which context that
> variable was defined, it switch there and with a little hack, picks
> the value from there.
>
> The code for both functions is:
>
> local lPersistentVariablesA
> global gVar
>
> function captureVariable pVariable
>    put lPersistentVariablesA[pVariable] into tContextsRaw
>    put 0 into tNum
>    repeat for each line tLine in tContextsRaw
>        add 1 to tNum
>        put return & tNum & comma & tLine after tBuf
>    end repeat
>    delete char 1 of tBuf
>    set the cREVScriptDebugMode of stack "revPreferences" to true
>    set the debugcontext to (item 1 of line -2 of tBuf)
>    put format("global gVar; put %s into gVar", pVariable) into tCmd
>    debugdo tCmd
>    set the debugcontext to empty
>    set the cREVScriptDebugMode of stack "revPreferences" to false
>    return gVar
> end captureVariable
>
> on newPersistentVariable pVariable
>    put the executioncontexts into lPersistentVariablesA[pVariable]
> end newPersistentVariable
>
> Now, why this is useful? Well, as you can see from the code, we have
> an array called lPersistentVariablesA, we could simply loop the keys
> of that array and capture and save all variables on shutdownRequest.
> We could modify the newPersistentVariable to check for the saved
> content and insert it back.
>
> Whats wrong with my current code? (A-Ha!) Right now, if you nest to
> many handlers, the context switch fails somehow... it's hard to debug
> this. I think that as Rev exits the handlers it drops the contexts
> (can we call that backtracking?). So if we go from firstHandler into
> secondHandler into thirdHandler, then in the thirdHandler we can
> capture variables from them all, but if we go from firstHandler into
> secondHandler out of secondHandler and into thirdHandler, then
> anything from secondHandler is lost.
>
> Anyway, it still a nice hack and it still useful. I've developed this
> to use with CGI programming, and in CGIs most things happen in the
> startup script or very near it, so I can still use these routines to
> pick variables from contexts that I know are still alive.
>
> How to solve this? Well, I don't know, I just wanted to play and try
> to build myself something that would allow me to freeze the execution
> contexts in time so that I could re-use them later (still trying to
> create state out of the stateless nature of cgis, order from
> chaos...).
>
>
> Andre
>
> --
> http://www.andregarzia.com All We Do Is Code.
> _______________________________________________
> use-revolution mailing list
> use-revolution at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-revolution
>
>
> _______________________________________________
> use-revolution mailing list
> use-revolution at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-revolution
>



-- 
http://www.andregarzia.com All We Do Is Code.



More information about the use-livecode mailing list