A few years ago there were flame wars here as to whether Scheme was Lisp or not and if I remember correctly, E. said at the time that Scheme resembled Algol more that CL as Scheme use exclusively static scoping (I hope I remember correctly). I believed him of course, but did not fully understand what that meant.
Is not static (or lexical) scoping generally regarded as safer and better than dynamic scoping? What are the advantages of dynamic scoping if we do not take the simplicity of implementation into account?
Please try to give a simple (idiotproof) explanation.
(BTW: The email address does not work any more.)
TIA, JB
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
On Wed, 10 Sep 2003 12:51:18 +0200, jblazi <jbl...@hotmail.com> wrote: > A few years ago there were flame wars here as to whether Scheme was > Lisp or not and if I remember correctly, E. said at the time that > Scheme resembled Algol more that CL as Scheme use exclusively static > scoping (I hope I remember correctly). I believed him of course, > but did not fully understand what that meant.
> Is not static (or lexical) scoping generally regarded as safer and > better than dynamic scoping? What are the advantages of dynamic > scoping if we do not take the simplicity of implementation into > account?
> Please try to give a simple (idiotproof) explanation.
FOO is a simple function which just prints to *STANDARD-OUTPUT*. But because *STANDARD-OUTPUT* is dynamically scoped you can easily "redirect" FOO's output to another stream without changing FOO.
jblazi wrote: > A few years ago there were flame wars here as to whether Scheme was Lisp > or not and if I remember correctly, E. said at the time that Scheme > resembled Algol more that CL as Scheme use exclusively static scoping (I > hope I remember correctly). > I believed him of course, but did not fully understand what that meant.
Yes, that is a general problem with gurus - people believe them although they don't fully understand them.
For this particular example, it is again important to note that CL and Scheme serve different communities. Schemers want a minimal language with no unnecessary overhead. Since dynamic scoping can easily be simulated on top of lexical scoping - with no real disadvantages - it doesn't make sense to include it in a language that heads for minimalism. (For example, one of the lambda papers by Sussman/Steele illustrates a simulation.)
In a language that heads for completeness, the inclusion of dynamic scoping makes perfect sense - that's why CL has it.
> Is not static (or lexical) scoping generally regarded as safer and better > than dynamic scoping? What are the advantages of dynamic scoping if we do > not take the simplicity of implementation into account?
That's not correct - lexical scoping is not generally safer and better than dynamic scoping. It's only the safer and better _default_ scoping.
Lexical and dynamic scoping allow you to express different things. If you don't care about the difference it's a good bet that lexical scoping is what you want. If you care about it you can improve the design of your code by sometimes going for dynamic scoping.
> Please try to give a simple (idiotproof) explanation.
-- Pascal Costanza University of Bonn mailto:costa...@web.de Institute of Computer Science III http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)
> > A few years ago there were flame wars here as to whether Scheme was > > Lisp or not and if I remember correctly, E. said at the time that > > Scheme resembled Algol more that CL as Scheme use exclusively static > > scoping (I hope I remember correctly). I believed him of course, > > but did not fully understand what that meant.
> > Is not static (or lexical) scoping generally regarded as safer and > > better than dynamic scoping? What are the advantages of dynamic > > scoping if we do not take the simplicity of implementation into > > account?
> > Please try to give a simple (idiotproof) explanation.
> * (defun foo (x) (format t "Result: ~A" (* x x)))
> FOO is a simple function which just prints to *STANDARD-OUTPUT*. But > because *STANDARD-OUTPUT* is dynamically scoped you can easily > "redirect" FOO's output to another stream without changing FOO.
The question is, whether that is a useful method to implement an API.
Problem: implement an API (functions, datatypes, ...) for writing to streams
What is a useful pattern to do that?
The Common Lisp 'solution': do almost everything at once.
- special printing functions that take some stuff as parameters and other stuff from special variables (PRINC, ...) - general printing functions that take a wide variety of parameters and defaults from special variables for most/all (WRITE !!!) - low-level printing functions (WRITE-CHAR, WRITE-BYTE, ...) - generic function which specializes of stream and object and also can look at special variables (PRINT-OBJECT, ...) - printing function with special domain specific programming language and compiler (FORMAT, FORMATTER)
So Common Lisp mixes happily all kinds of parameter passing (required, optional, keyword, default-values, ...). Sometimes STREAM is a keyword arg, sometimes it is the first required arg, sometimes it is second and optional, ...
The last thing that is missing is the usage of printing context objects (-> graphic contexts in CLIM).
I'm not really sure, whether the implicit shadowing/passing of parameters via special variables is really a good pattern for this problem. Ideas and discussions welcome.
Edi Weitz <e...@agharta.de> writes: > FOO is a simple function which just prints to *STANDARD-OUTPUT*. But > because *STANDARD-OUTPUT* is dynamically scoped you can easily > "redirect" FOO's output to another stream without changing FOO.
This is particulary useful when you're not in a position to change FOO at all, e.g. I use the following in lispworks to pick up the output of the room function:
In article <bjn8fr$th...@f1node01.rhrz.uni-bonn.de>, Pascal Costanza wrote: > jblazi wrote:
>> Is not static (or lexical) scoping generally regarded as safer and better >> than dynamic scoping? What are the advantages of dynamic scoping if we do >> not take the simplicity of implementation into account?
> That's not correct - lexical scoping is not generally safer and better > than dynamic scoping. It's only the safer and better _default_ scoping.
Is static scope and lexical scope the same thing, or is there differences like the difference between strong typing and static typing?
-- -- Gisle Sælensminde Computational biology unit, University of Bergen, Norway Email: gi...@cbu.uib.no
On Wed, 10 Sep 2003 14:18:54 +0000, Gisle Sælensminde wrote: > Is static scope and lexical scope the same thing, or is there differences > like the difference between strong typing and static typing?
It is the same.
--, JB
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Ok, thx to all of you. But is it not true that the master looked down upon Scheme as it was a statically scoped language? Or did I misunderstand Him? (And this was why He said that Scheme was in reality more related to Algol than to CL?)
--, JB
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
jblazi <jbl...@hotmail.com> writes: > Is not static (or lexical) scoping generally regarded as safer and better > than dynamic scoping?
By most of my friends, yes. You're asking a statistical question that is hard to answer in general.
> What are the advantages of dynamic scoping if we do > not take the simplicity of implementation into account?
You never get anything for free. Conservation laws apply even to language design. So, if safety is gained, what is lost? Ease of bludgeoning others' code into doing what you need. (The flip side of protection: "protection" protects the guy on the inside. Not so good for the guy on the outside...)
That is, it's a rapid prototyping aid. You find that functions always come with a bunch of -- I'll use the connotationally best word I can find -- "felicitous" hooks into their behavior (you might read that as "accidental" or "dangerous" if you are cynical) since you can't make functions easily airtight except by making them never call any other function... and even then you probably have to lock out interrupts.
Of course, you might say, you could communicate with the author and get them to properly hook their code. Or you could use only open source. The former takes time. The latter creates a source split. Once again, my bottom line message: you never get anything for free.
jblazi <jbl...@hotmail.com> wrote in message <news:pan.2003.09.10.10.51.17.422000@hotmail.com>... > A few years ago there were flame wars here as to whether Scheme was Lisp > or not and if I remember correctly, E. said at the time that Scheme > resembled Algol more that CL as Scheme use exclusively static scoping (I > hope I remember correctly). > I believed him of course, but did not fully understand what that meant.
> Is not static (or lexical) scoping generally regarded as safer and better > than dynamic scoping?
It's regarded as better optimizeable.
> What are the advantages of dynamic scoping if we do
Program in Lisp for a year and you will see. The advantage of dynamic scoping is---unsurprisingly---that you can access variables that are local to your dynamic context without being physically confined to the immediately enclosing program text.
Dynamic variables can, in a completely invisible way, pass arbitrary information across nested function calls. Invisible means that the intermediate functions in the chain are not involved in the data path; they don't take any additional parameters which they have to pass down. The entire dynamic environment with its dynamic bindings is implicitly passed down.
> not take the simplicity of implementation into account?
What makes you think dynamic scoping is all that simple? For one thing, in the presence of threads, the variable references have to be thread specific. Each thread can independently override a dynamic variable in its own dynamic contexts. This requires some measure of support from the multithreading substrate.
> Please try to give a simple (idiotproof) explanation.
Each LET block temporarily binds the standard special variable *print-base* to a new value. This binding is visible to the PRINT function, which renders the integer value in the specified base. When the LET block terminates, the value of *print-base* is restored to whatever it was outside of that block.
No parameter was passed to the PRINT function to specify base. If the PRINT function were buried in some other code, it would still be influenced. Here is another example:
(defun print-hello () (format t "hello, world~%"))
The output of the function is captured in a string which forms the return value of the WITH-OUTPUT-TO-STRING form. We did not require the cooperation of the PRINT-HELLO function. Transparently to that function, we communicated our wish to the I/O library to have standard output go to a string stream.
Needless to say, you can't do these tricks with lexical scoping, because lexical scoping is completely devoid of the ``action at a distance'' semantics; to influence anything lexically, you have to go to that site and introduce your lexical bindings in the source code which you must then recompile.
> > Is not static (or lexical) scoping generally regarded as safer and better > > than dynamic scoping? > > What are the advantages of dynamic scoping if we do > > not take the simplicity of implementation into account?
> You find that functions always > come with a bunch of -- I'll use the connotationally best word I can > find -- "felicitous" hooks into their behavior (you might read that as > "accidental" or "dangerous" if you are cynical) since you can't make > functions easily airtight except by making them never call any other > function... and even then you probably have to lock out interrupts.
Btw, I wrote this thinking you'd meant "advantages as the default kind of binding" not "advantages of having both vs of just having one".
Of course, in the case where you have both, you can advertise exactly the hooks you want, and so everything doesn't end up "dangerous". There is a tiny amount of danger even in documented specials, but it's mostly outweighed by the benefit of being able to tune a program.
On Wed, 10 Sep 2003 14:56:42 -0400, Kent M Pitman wrote: > Btw, I wrote this thinking you'd meant "advantages as the default kind of > binding" not "advantages of having both vs of just having one".
> Of course, in the case where you have both, you can advertise exactly > the hooks you want, and so everything doesn't end up "dangerous". > There is a tiny amount of danger even in documented specials, but it's > mostly outweighed by the benefit of being able to tune a program.
Thx. This is rather interesting. So having both types of typing gives you complete control. Would you consider CL's having both static and dynamic scoping such an important feature of the language that you would say that Scheme resembles Algol more than CL (as Scheme uses only static scoping as a matter of principle)?
JB
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
jblazi <jbl...@hotmail.com> writes: > Would you consider CL's having both static and dynamic > scoping such an important feature of the language that you would say that > Scheme resembles Algol more than CL (as Scheme uses only static scoping as > a matter of principle)?
Allow me to point out that any decent-sized Scheme system has mechanisms for dynamic scope (usually called fluid-let in Scheme-land). You need some abstraction for capturing the `ambient state' of the world without explicitly passing it to every function in the world.
jblazi wrote: > On Wed, 10 Sep 2003 14:56:42 -0400, Kent M Pitman wrote:
>>Btw, I wrote this thinking you'd meant "advantages as the default kind of >>binding" not "advantages of having both vs of just having one".
>>Of course, in the case where you have both, you can advertise exactly >>the hooks you want, and so everything doesn't end up "dangerous". >>There is a tiny amount of danger even in documented specials, but it's >>mostly outweighed by the benefit of being able to tune a program.
> Thx. This is rather interesting. So having both types of typing gives you > complete control.
Nitpick: You don't mean typing, you mean scoping. Typing is something different.
> Would you consider CL's having both static and dynamic > scoping such an important feature of the language that you would say that > Scheme resembles Algol more than CL (as Scheme uses only static scoping as > a matter of principle)?
No, I don't think so. It's relatively easy to implement dynamic scoping in other languages. For example, Java has a similar concept called "thread local" (see the ThreadLocal class). If you look at its implementation you will find out that it is almost trivial to implement.
Common Lisp is a more or less a complete collection of best practices gained from decades of experience with various Lisp dialects. The fact that Common Lisp has included the notion of dynamic scoping in its standard is just a reflection of the fact that it is actually useful in practice.
AFAICT, most Scheme implementations provide at least one form of dynamic scoping. It seems to me that many people outside the Lisp culture consider dynamic scoping to be an evil thing because of its bad reputation it has gotten when it was the default scoping mechanism. That's why it seems to be more or less completely abandoned in mainstream languages. However, for example I have seen reasonable amounts of Java code that are in fact just tedious and error-prone hand-written simulations of dynamic scoping. (For example the source code for the Java compiler from JDK 1.3 upwards has lots of code like that.)
Indeed, dynamic scoping by default can lead to very hard to detect bugs. You have to make a conscious decision for dynamic scoping for specific cases and have to be aware of its consequences. That's why in Common Lisp, dynamically scoped variables are specially marked by asterisks around their names, or why in ISLISP a special mechanism is provided to access dynamically scoped variables.
Pascal
-- Pascal Costanza University of Bonn mailto:costa...@web.de Institute of Computer Science III http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)
* Espen Vestre <espen@*do-not-spam-me*.vestre.net> | Edi Weitz <e...@agharta.de> writes: | | > FOO is a simple function which just prints to *STANDARD-OUTPUT*. But | > because *STANDARD-OUTPUT* is dynamically scoped you can easily | > "redirect" FOO's output to another stream without changing FOO. | | This is particulary useful when you're not in a position to | change FOO at all, e.g. I use the following in lispworks to | pick up the output of the room function: | | CL-USER 7 > (with-output-to-string (*standard-output*) (room nil)) | " | Total Size 81702K, Allocated 44499K, Free 37041K | "
jblazi wrote: > On Wed, 10 Sep 2003 15:20:48 +0200, Pascal Costanza wrote: > > The following paper is an overview with examples and references to other > > papers: http://progwww.vub.ac.be/~wdmeuter/PostJava/Costanza.pdf > Ok, thx to all of you. > But is it not true that the master looked down upon Scheme as it was a > statically scoped language? Or did I misunderstand Him? (And this was why > He said that Scheme was in reality more related to Algol than to CL?)
One difference between scheme and algol is that Scheme gives you everything you need to implement dynamic scope if you want it, and Algol doesn't. One of the reasons why teachers like Scheme so much is that, by implementing dynamic scope, they can show students the difference between dynamic and lexical scope. When you just demonstrate the difference in a language where it's pre-built, some students won't "get it" because they don't see how it works.
In article <3F6F613F.B0151...@sonic.net>, Ray Dillinger <b...@sonic.net> wrote: > One difference between scheme and algol is that Scheme gives you > everything you need to implement dynamic scope if you want it
Really? How do you do it? (And in particular, how do you do it so it's thread-safe?)
> In article <3F6F613F.B0151...@sonic.net>, Ray Dillinger <b...@sonic.net> wrote:
> > One difference between scheme and algol is that Scheme gives you > > everything you need to implement dynamic scope if you want it
> Really? How do you do it? (And in particular, how do you do it so it's > thread-safe?)
Honestly? I don't. I've never needed it. I have seen this bit of wizardry/hackery over on CLS though from people who thought it was indispensable, or just neat, which involved directly mutating and accessing a single dynamic-environment structure that was defined in the top-level lexical environment, giving it as an argument the call-chain extant at the point of access so it could give them the right dynamic environment frame. If you wanted it multithreaded, I think the first approximation would be that you'd have to have a separate call-chain variable encapsulated in it for each thread. But multithreading's not standard and the implementation I saw didn't use it. They implemented it, I guess, for the same reasons I occasionally implement objects in scheme if some particular program needs OO technique; it's a technique or usage pattern rather than something directly provided and prepackaged.
Scheme is a language without the idea of what CL and C++ programmers call "threads", although a lot of implementations provide them as an extension and there's a proposed standard for multithreading scheme now over on srfi.schemers.org. I don't happen to like this proposal, but the people who are actually implementing software that really needs to be multithreaded say that it does what they want and is easier to use than doing it with continuations, so... they've got a library or two now to do it with. What scheme has instead of threading is fully re-entrant continuations, which are powerful, especially in combination with fully general tail call optimization, but very different.
I can handle threads, and actually like fully re-entrant continuations - but the idea of handling both at once in the same program, especially if running threads simultaneously on multiple CPU's, gives me the jibblies about any meaningful use of the word 'safe.' I don't think it's necessarily unsolvable, but I would not like to trust anyone's implementation for "safety" in the presence of _both_ of these constructs unless I knew that it had been specifically designed and debugged for safety in the presence of _both_ constructs.