Dynamic Scope as an idiom - or - to let or not to let

Started by Tim Johnson, April 13, 2008, 11:40:57 AM

Previous topic - Next topic

Tim Johnson

I have backgrounds in both rebol and python - which compare I suppose -

as do common lisp and newlisp in terms of scoping rules.

Be that as it may - I've seen arguments ad naseum about dynamic vs lexical

scoping - but what I'm really interested in how to use newlisp scoping to

my advantage.



I find that I've been using 'let a lot - and maybe more than I should.

So I would welcome comments, caveats, rules of thumb, etc on how

to take advantage of dynamic scoping. I've not used 'local at all.

Would be great to see further comment on that function - there's not a

lot about it in the manual.



Thanks

Tim
Programmer since 1987. Unix environment.

cormullion

#1
There's a post at Jeff's old site http://artfulcode.nfshost.com/files/why-not-dynamic-scope.html#unique-entry-id-25">//http://artfulcode.nfshost.com/files/why-not-dynamic-scope.html#unique-entry-id-25. It's all good reading... And some discussion on this forum in places - http://www.alh.net/newlisp/phpbb/viewtopic.php?t=1657">//http://www.alh.net/newlisp/phpbb/viewtopic.php?t=1657.



I don't feel able to say wise things about the subject. But I like using local for when I don't know what the value's going to be for a symbol when the function begins - why waste time setting it to empty when you can get it done for you, and I don't see what's wrong with using let a lot. Some people like doing all the work in a letn definition block.  My simple rule of thumb (not yet posted to http://rulesofthumb.org/">//http://rulesofthumb.org/ :)) is to make sure that I know where symbols are defined before I refer to them; either they're in the function's argument list, in the let or local list, or they've got asterisks around them and are global...

Jeff

#2
let-binding is used quite a bit in most lisp-like languages, as well as ocaml.  It is nicer than assignment expressions because it explicitly declares a variable to be local to the block.



Dynamic scoping and let-binding are different ballparks.  Let-binding is a local binding to a block, as opposed to global bindings that set/setq perform.



Dynamic scoping simply means that a variable's value is its value in the current scope.  If you call f() from g(), and a = 10 in g(), then it will equal 10 in f() as well (unless f() uses let-binding to shadow a).



Lexical scoping means that the program is analyzed lexically and functions lookup variables in the environment in which they were defined, rather than in which they were executed.



So, if f() is called from g(), and a=10 in g(), then the value of a may not even be visible to f(), because f() only knows about variables in its own environment.



Let binding has more to do with local/global scope than dynamic/static.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Tim Johnson

#3
Jeff, I'm familiar with let from elisp and rebol (only rebol calls it 'use).

I think that I understand the issues of scoping - and I have bookmarked

what you've written about the issue.



I am just "fishing" - no, no, not trolling :-)

for some tips that will help me to take advantage of dynamic scoping.



For instance in rebol I try to use naming conventions, like *globalvar1*,

*globalvar2*, etc.... since rebol allows asterisks as legitimate symbol name

components.

Thanks!

Tim
Programmer since 1987. Unix environment.

cormullion

#4
As well as - or instead of - the asterisk, you can use contexts. This is Lutz'  suggestion:


Quote from: "Lutz"Just put all globals in its own context 'global' or 'gl' or even shortening to capital 'G' for those who hate typing (like myself ;-))


(set 'G:database "/usr/home/joe/data/database.lsp")
(set 'G:n-config 12345)


A context qualified variable is global by definition, because contexts names are global. It also keeps all globals together in one place for inspection or serializing with


(save "appglobals.lsp" 'G)

Jeff

#5
The `save` command is useful with dynamic scope.  It is much like a continuation - you are saving something similar to the current stack frame.  You lose shadowed variables, though:


(set 'a "bar")
(let ((a "foo")) (save "foo.lsp"))


That will save `(set 'a "foo")` to foo.lsp.  I use this as a way to preserve state in cgi applications using sessions.  I give the client a unique id and store it in a cookie with a time stamp.  If the user opens another page, I can restore all variables by loading the file - (load (string 'session-id ".lsp")).



In a persistent process, you can do tricks like saving the state a location A and then, if something fails afterward, reloading it later:


(save "temp.lsp")
(unless (catch (do-something-risky) 'result) (load "temp.lsp"))
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Tim Johnson

#6
Thanks folks. You're talking about methods that I am very familiar with

in rebol!



BTW: rebol has a poorly documented feature that I use a lot and is IMHO

very valuable:

An anonymous context wrapping a function which is made global by

the set 'function func syntax. "words" declared inside of

the context or the function body are total private as far as I can tell,

and are pesistent (continuations)

example:
context[set 'f func[][m: 1]]
Could 'let or 'local be used at the top level with a function defined within

made global similarly?

The following:
(let (f) (define(f) println "here"))
doesn't seem to 'export' 'f

- Oh, I know about the default functor - very handy, I think.

tim
Programmer since 1987. Unix environment.

Jeff

#7
No.  You mean closures, not continuations.  You can do that with a context functor:


(define (foo:foo) (println bar))
(setq foo:bar "Tim")
(foo) ; => prints Tim
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Tim Johnson

#8
You're correct. My typo. Additionally:

I've had just a couple minutes to play with

'save and it looks like it is more flexible and a bit different from

rebol/save. In fact since my bread-and-butter is CGI, it's going to

_extremely_ valuable for me.

Thanks for the introduction.

Tim
Programmer since 1987. Unix environment.