Warning: This thread is not a request for help on any particular problem. It's just for discussion, so if you're not into that sort of thing, don't blame me if you decide to post anyway.
If there were a statically, implicitly typed Lisp, would you use it? What qualities of dynamic typing would you miss?
* sajiimori | If there were a statically, implicitly typed Lisp, would you use it?
Common Lisp is already statically, implicitly typed. All objects are of type T, and this is very rigourously enforced.
| What qualities of dynamic typing would you miss?
You may have noticed that every language worth using these days has (added) an object system that carries type information in the objects. You appear to want to take a step backwards in this respect. Why?
-- Erik Naggum | Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
sajiimori wrote: > Warning: This thread is not a request for help on any particular problem. > It's just for discussion, so if you're not into that sort of thing, don't > blame me if you decide to post anyway.
> If there were a statically, implicitly typed Lisp, would you use it? What > qualities of dynamic typing would you miss?
Dynamicity? ;)
Static type systems are not bad per se, especially those based on type inference. They can in fact be useful to determine certain properties of your programs that sometimes might help you.
However, what sucks in most statically typed languages is that their type systems are enforced at compile time without any unobtrusive way to switch to dynamic typing. The mindset of static typers seems to be that when the compiler complains about a static type error, you should not be allowed at all to run your program. This doesn't make sense, especially in scenarios in which a run of an erroneous program could actually help you to detect the source of a problem. From an engineering point of view, it does not make sense to restrict your toolset.
What good dynamically typed languages give you beyond better debugging facilities is the ability to change a program at run time, which means adding, removing or changing features dynamically. Especially the removal of features is not handled very well in statically typed languages. Dynamic software evolution enables a whole range of new deployment models, like running your software on a web server and being able to update it without any downtimes.
It's important to note that the kind of type system is not the only important factor, and that the default typing "philosophy" of a language does not necessarily preclude the switch to the other one.
Examples:
- Many people are scared when they hear about changing features of a program at run time. However, notions like keyword arguments and generic functions in Common Lisp or categories in Smalltalk make this a relatively harmless process. The fact that changing a C++ program at run time would wreak havoc isn't a compelling argument against dynamic software evolution.
- There are approaches to add static type checking to dynamically typed languages as an additional tool, without strictly enforcing what static typers call "type soundness". For example, CMU Common Lisp (CMUCL) and Strongtalk are good examples in this regard.
- Likewise, modern Java IDEs like Eclipse have implemented their own Java compiler that allows them to treat static type soundness as an optional feature. In Eclipse it is possible to run a Java program even when the Java compiler emits compile-time errors. Obviously, this degree of flexibility is needed in the "real world".
Still, Java's static type system is one of the worst, and will even become worse in JDK 1.5. I am not aware of a language with a reasonably well-designed static type system that allows this kind of optional switch to dynamic type checking.
- Again likewise, there are dynamically typed languages out there that still suck very badly. Again, whether a language is dynamically or statically typed does not determine whether it is a good language. Programming languages are holistic entities, in the sense that all the distinguishing features have to complement each other well.
Pascal
-- Tyler: "How's that working out for you?" Jack: "Great." Tyler: "Keep it up, then."
sajiimori wrote: > Warning: This thread is not a request for help on any particular problem. > It's just for discussion, so if you're not into that sort of thing, don't > blame me if you decide to post anyway.
> If there were a statically, implicitly typed Lisp, would you use it? What > qualities of dynamic typing would you miss?
Yes, I would use it, as long as any conformant Common Lisp program would run in it. Otherwise, I would not be so interested.
"sajiimori" <myusern...@hotmail.com> writes: > Warning: This thread is not a request for help on any particular problem. > It's just for discussion, so if you're not into that sort of thing, don't > blame me if you decide to post anyway.
> If there were a statically, implicitly typed Lisp, would you use it?
Possibly.
> What qualities of dynamic typing would you miss?
What qualities of dynamic typing would be missing?
> Common Lisp is already statically, implicitly typed. All objects are > of type T, and this is very rigourously enforced.
I don't know if you're being serious, but the rule that all objects are of type T means that if X is an object, the statement "X is of type T" carries no information. I don't know how you could consider something a static type system when it doesn't offer any static distinction between objects.
> You may have noticed that every language worth using these days has > (added) an object system that carries type information in the objects.
Static and/or implicit typing doesn't forbid objects from carrying type information, so I don't see your point.
> You appear to want to take a step backwards in this respect. Why?
You folks sure are touchy -- I didn't even say that I want static or implicit typing. I thought it would take at least a few posts before the rudeness began.
We're having a nasty winter. Wait till spring and try again.
kenny
--
clinisys, inc http://www.tilton-technology.com/ --------------------------------------------------------------- "[If anyone really has healing powers,] I would like to call them about my knees." -- Tenzin Gyatso, the Fourteenth Dalai Lama
> The mindset of static typers seems to be > that when the compiler complains about a static type error, you should > not be allowed at all to run your program. This doesn't make sense, > especially in scenarios in which a run of an erroneous program could > actually help you to detect the source of a problem.
Interesting... Do you have an example of how running a program can lead to the discovery of the source of a static typing error? I would think that since nothing that happens at runtime can affect static typing, there would be no useful information to glean about such an error.
> From an engineering > point of view, it does not make sense to restrict your toolset.
My first impulse is to agree, but the biggest (generally agreed upon) benefit of static typing is that type errors are caught at compile-time, and that benefit can only be reaped by restricting yourself from doing anything that would violate the system. I guess it depends on what freedoms you'd be willing to forfeit (if any) to have that feature -- which is sort of what my original question was about.
> What good dynamically typed languages give you beyond better debugging > facilities is the ability to change a program at run time, which means > adding, removing or changing features dynamically. Especially the > removal of features is not handled very well in statically typed > languages. Dynamic software evolution enables a whole range of new > deployment models, like running your software on a web server and being > able to update it without any downtimes.
These ideas are still pretty new to me. What do you mean by "removing features", and why does the type system affect it so much?
> It's important to note that the kind of type system is not the only > important factor, and that the default typing "philosophy" of a language > does not necessarily preclude the switch to the other one.
That's exactly what I'm hoping for, because I'm trying to make a Lispy language that uses strong, static, implicit typing (just as an experiment -- I don't know if I would even use such a language in place of CL).
> - There are approaches to add static type checking to dynamically typed > languages as an additional tool, without strictly enforcing what static > typers call "type soundness". For example, CMU Common Lisp (CMUCL) and > Strongtalk are good examples in this regard.
If I were still running a Unix, I'd check out CMUCL -- as it is, I've only seen CLISP and Corman, neither of which catch type errors at compile time. :( Would CMUCL warn about this during compile-time? If not, do you think it should?
(defun x-plus-y (x y) (+ x y))
(defun test () (x-plus-y 5 "asdf"))
> Again, whether a language is dynamically or > statically typed does not determine whether it is a good language. > Programming languages are holistic entities, in the sense that all the > distinguishing features have to complement each other well.
Of course! So, as a variant of my original question: In a statically, implicitly typed Lisp, do you think the features would still complement each other well?
> Common Lisp is already statically, implicitly typed. All objects are > of type T, and this is very rigourously enforced.
* sajiimori | I don't know how you could consider something a static type system | when it doesn't offer any static distinction between objects.
I think you may want to return to your books on types and focus on the definition of static type analysis. The Common Lisp type system does in fact satisfy the definition of a static type system in that both you and the compiler always know the type of the object statically: It is always T, and you can never violate this static type.
> You may have noticed that every language worth using these days has > (added) an object system that carries type information in the objects.
| Static and/or implicit typing doesn't forbid objects from carrying type | information, so I don't see your point.
Well, consider this: all Common Lisp objects (of type T) carry type information. Are you beginning to see the point?
> You appear to want to take a step backwards in this respect. Why?
| You folks sure are touchy -- I didn't even say that I want static or | implicit typing. I thought it would take at least a few posts before | the rudeness began.
If you are so concerned about rudeness, why are you rude towards us? You get one simple question about your motives, and you start talking about «you folks». Your brain is malfunctioning, sajiimori.
You have made it clear that you are incapable of processing answers to your questions, incapable of seeing the point I made when you type it in yourself, incapable of polite conversation, and so nervous about your objectives that you become defensive when questioned about them.
Go away, annoying troll.
-- Erik Naggum | Oslo, Norway 2004-026
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
* sajiimori | If I were still running a Unix, I'd check out CMUCL -- as it is, I've | only seen CLISP and Corman, neither of which catch type errors at | compile time. :( Would CMUCL warn about this during compile-time? If | not, do you think it should? | | (defun x-plus-y (x y) | (+ x y)) | | (defun test () | (x-plus-y 5 "asdf"))
I keep wondering why the static type crowd always make up this kind of examples.
In the Common Lisp world, you are supposed to be conscious when you write your code, and the above fragment suggests that you are not, but want the compiler to wake you up from your code-writing coma.
One reason to cater to the comatose programmers is that static typing with a wide variety of types adds a lot more things to think about. The other solution to this problem is dynamic typing.
If you want to understand what is going on here, you have to begin by realizing that both static and dynamic typing are answers to another, logically preceding question. The static type crowd solved a problem when people passed around machine words with different meanings. «I know», said that static type genius, «I'll let the compiler keep track of all the types and refuse to run the program with values of random types confusing the machine!». In another office, far away, sat the dynamic typing genius and thought «I know, I'll make all values self- determine their types!». The latter genius laid the foundation for the reinvention of object-orientation with run-time type information, which needed to be added to the static type genius's world view at at heavy cost.
If you write the above code in Common Lisp, the purpose of running it will be to investigate the response to type errors. You will observe that you invoke the debugger. One of the things you could do then is to realize that the function that was called should be a generic function, and you can back out of the call, redefine the function x-plus-y, and resume execution by retrying the call. Another thing you could do is to realize that you had made a mistake in the caller. In this case, you would back out of the call to test, instead, and redefine that function and resume execution by calling the new test function.
Please think about how this is different from the static typing systems you appear to know better than Common Lisp.
| So, as a variant of my original question: In a statically, implicitly | typed Lisp, do you think the features would still complement each | other well?
As long as you do not understand what you already have, there is no point in answering your question about what would be.
And /calm down/, please. Say to yourself that you are not «touchy», and that you have to /think/ when you feel uncomfortable, not lash out at whoever you think makes you feel uncomfortable. Can you do this?
-- Erik Naggum | Oslo, Norway 2004-026
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
* sajiimori | I'm sure that's just the tip of the iceberg, but I haven't been using Lisp | long enough to discover many significant benefits of dynamic typing.
We already knew that by now. You are probably the millionth person to come to Common Lisp thinking that the only solution to your problems in making programs work correctly is static type analysis, because that was the solution to the same problem in the previous language you tried to learn by trial-and-error. Trust me, the solution is not to add static type analysis to the language, it is to upgrade your brain to work with a new language and a new set of solutions to a new set of problems. Static type analysis leads to brain damage and it has to be repaired before you can deal with a world where others are not obliged to do only what you have advertised that you accept.
There is a golden rule about learning anything new. First, you look long and hard at it and determine that it is not something you already know. Then, you look at all the differences you can find and work hard to disregard any emotional responses of the sort «I already know this!» because you think you see a similarity. Finally, you approach it as something you have to learn, because you realize that you do not already know it. If you do not follow this golden rule, you will only succeed in treating all things that are somewhat similar as the same, and you will respond with things like «You folks sure are touchy» when you think you see something that is similar to something you already determined was the result of being «touchy». When you are mistaken in making such pronouncements, you get snubbed by people you have angered and you probably become even more certain that they are touchy, but you have in fact insulted them with your prejudice and they try to make you back off and take another look at the evidence. If you are not the kind of person who is able to disregard similarities and look for the surprising dissimilarity with curiosity, this will not work, and you will only deepen your conviction that you already understand what you see. I know what I think about you right now, but you have the option of responding with more curiosity and less judgment at any time. Some psychologists argue that this is a personality property and that some people naturally judge before they know what they look at, while others are naturally curious and defer judgment even when they know what they look at. Both need to do something unnatural at times and break the natural habit, but if you are the judging type and something uncomfortable shows up, your tendency to judge before you think will most probably overwhelm any residiual curiosity. You make a distinct impression of being very strongly judging, so this is a very strong strong request for you to back off from your judgments and take a closer look at the evidence.
-- Erik Naggum | Oslo, Norway 2004-026
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
> If I were still running a Unix, I'd check out CMUCL -- as it is, I've only > seen CLISP and Corman, neither of which catch type errors at compile time. > :( Would CMUCL warn about this during compile-time? If not, do you think > it should?
> (defun x-plus-y (x y) > (+ x y))
> (defun test () > (x-plus-y 5 "asdf"))
Ideally they could catch this. But consider the correct implementation using a compiler macro:
(declaim (inline x-plus-y)) (defun x-plus-y (x y) (+ x y))
(define-compiler-macro x-plus-y (x y) `(+ ,x ,y))
Now try defining test and compiling it:
* (defun test () (x-plus-y 5 "asdf"))
* (compile 'test) ; Compiling lambda nil:
; In: lambda nil
; (x-plus-y 5 "asdf") ; ==> ; (+ 5 "asdf") ; Warning: Lisp error during constant folding: ; Argument y is not a number: "asdf". ; ; Warning: This is not a (values &optional number &rest t): ; "asdf" ; ; Compiling Top-Level Form:
; Compilation unit finished. ; 2 warnings
The error is instantly discovered in SBCL because it compiles all forms.
"That is to say, if a program compiles in a strong, statically typed language, it just means that it has passed some tests. It means that the syntax is guaranteed to be correct (Python checks syntax at compile time, as well. It just doesn't have as many syntax contraints). But there's no guarantee of correctness just because the compiler passes your code. If your code seems to run, that's also no guarantee of correctness... The only guarantee of correctness, regardless of whether your language is strongly or weakly typed, is whether it passes all the tests that define the correctness of your program. "
Along the way he cites Robert Martin coming to the same conclusion:
Martin also contradicts your lack of enthusiasm for dynamic languages:
"I thought an experiment was in order. So I tried writing some applications in Python, and then Ruby (well known dynamically typed languages). I was not entirely surprised when I found that type issues simply never arose. My unit tests kept my code on the straight and narrow. I simply didn't need the static type checking that I had depended upon for so many years.
"I also realized that the flexibility of dynamically typed langauges makes writing code significantly easier. Modules are easier to write, and easier to change. There are no build time issues at all. Life in a dynamically typed world is fundamentally simpler.
"Now I am back programming in Java because the projects I'm working on call for it. But I can't deny that I feel the tug of the dynamically typed languages. I wish I was programming in Ruby or Python, or even Smalltalk."
So maybe you should get off Usenet and do some Lisp and find out what you are missing.
kenny
--
http://www.tilton-technology.com/ --------------------------------------------------------------- "[If anyone really has healing powers,] I would like to call them about my knees." -- Tenzin Gyatso, the Fourteenth Dalai Lama
> If you write the above code in Common Lisp, the purpose of running it > will be to investigate the response to type errors. You will observe > that you invoke the debugger. One of the things you could do then is > to realize that the function that was called should be a generic > function, and you can back out of the call, redefine the function > x-plus-y, and resume execution by retrying the call. Another thing > you could do is to realize that you had made a mistake in the caller. > In this case, you would back out of the call to test, instead, and > redefine that function and resume execution by calling the new test > function.
I too am a recent arrival to the Lisp camp am still not convinced as to the unconditionally superiority of the dynamic aspects of the type system.
What happens when the program is being put to actual use by actual end users, who outnumbers the programmer(s) who made the program many thousand times? The programmer(s) who made the program will not be there to do their magic stuff at the top level in the break loop when the program rolls over and falls into the break loop so to speak.
I guess you have to wrap everything important in a handler-case or ignore-errors with a handler that can restart/retry/shutdown/bugreport/etc. Just like you would do to for instance a java program to handle runtime errors.
But if this is the case, then is all this dynamic typing stuff only of benefit during development and debugging, and of no use during actual use by end users because at that time going into the break loop equals a crashed program?
> > My first impulse is to agree, but the biggest (generally agreed upon) > > benefit of static typing is that type errors are caught at compile-time,
> I think you are a bit behind the times. The hard-core, static-typing C++ > crowd has changed its mind:
Thanks, but I'm not particularly interested in arguments from authority.
Besides, the quote from Bruce Eckel doesn't seem to argue against static typing -- all it says is that the compiler can't guarantee that your program is correct (which should be obvious).
> Martin also contradicts your lack of enthusiasm for dynamic languages:
Sorry, I'll try to post with more enthusiasm next time. Do I need more smileys? (I guess I can't say the word 'static' without getting pidgeon-holed.)
> So maybe you should get off Usenet and do some Lisp and find out what > you are missing.
I wonder how you got the impression that I have not used Lisp? (This newsgroup seems to have a taboo against discussing language features.)
I think I may take your advice and stop posting here... everybody is so hostile. It's really shocking to go from a friendly community of developers (like the Gameboy Advance forum I visit often) to a group like this one. It really makes me lose a bit of faith in the Internet, and in human decency in general.
* Kristian Elof Sørensen | I too am a recent arrival to the Lisp camp am still not convinced as | to the unconditional superiority of the dynamic aspects of the type | system.
Nobody implied it was unconditionally superior. You have to lose this «one winner takes all» attitude. Different solutions can coexist. In fact, different solutions /must/ coexist for the proper solution to be applied to problems that differ from the historic problems to which they were the solutions. Think evolution. In the real world, there are no winners, only temporary advantages. The myth of the «winner» is probably the second most destructive myth that Western civilization has hoisted upon its population. (The most destructive myth is that of people being either «good» or «evil», which is the root cause of all injustice ever perpetrated by humans.)
| But if this is the case, then is all this dynamic typing stuff only of | benefit during development and debugging, and of no use during actual | use by end users because at that time going into the break loop equals | a crashed program?
What «this» refers to is not the case and none of the above follows.
If you insist that the way you view the world is the only only possible (as is implied by resorting to «unconditional superiority»), everything will turn out to run against your world-view sooner or later, and this will naturally be interpreted as there being something wrong with the world. For instance, when you equate a handled error condition with a crash, you look at only the most superficial quality of a failure: That it does something other than the user wanted. But most of the time, real-world applications have an extremely strong requirement to either complete their task to specification or not do any harm. The Common Lisp condition system is eminently able to make computers behave in the most rational way possible when they are unable to complete a task.
I strongly suggest that you not explore the boundary conditions until you are comfortable with the normal operating parameters. This means that you have to lose «unconditional», «all», «only», «of no use», etc.
Incidentally, type errors are irrelevant. They just do not happen in Common Lisp code as often as they do in languages where the compiler is responsible for catching them. It is understandable that someone who has been burned hard and often by compilers who never seem to be satisfied with one's code no matter how hard one tries, will believe that this kind of mistake is very important and stands between him and total disaster of the program. However, this is not how it works in Common Lisp, because Common Lisp systems do not crash. They are so forgiving and friendly that anyone who approaches them believing that they will be hostile and interpret their responses as if they could only have been hostile, will misunderstand and fight the system, much like they would people they mistakenly believe are hostile.
-- Erik Naggum | Oslo, Norway 2004-026
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
I think you will want to explicate what precisely you want from a static lisp. More on this below.
"sajiimori" <myusern...@hotmail.com> wrote in message <news:xg2Rb.27138$1e.19968@newsread2.news.pas.earthlink.net>... > Interesting... Do you have an example of how running a program can lead to > the discovery of the source of a static typing error? I would think that > since nothing that happens at runtime can affect static typing, there would > be no useful information to glean about such an error.
Many lispers seem to believe hardcore static fans suffer from tunnelvision. A system that statically catches type errors is subordinate to the goal of writing generally good code. For which analyzing statically verifiable errors is a possible resource.
Let's make the assumption that errors tend to cluster. Perhaps some other guy was experimenting with drugs and wrote some mind-altering code for three hours. With normal languages, the testing phase branches -- you have tests at compiletime, and another at runtime. You effectively lose the compiletime information at runtime.
/Static analysis does not mean it must run at compiletime./ What if I had a file from which I could import type data, which the static checker uses in helping diagnose the codebase? Or I could incrementally give static data and ask what some analyzer thinks. Imagine the implications for software engineering if we had tools which could say, "Check out module Frobule; there is a high incidence of problems in code which calls it."
I AM NOT impugning static analysis. Far from it; proving properties about code is wonderful. However, there is this insane presumption, orthogonal to static analysis, that says we must run screaming from errors with our hands over our ears. I don't think this is a fault in anyone, just our byzantine languages and educations that pressure us into being macho and hiding our faults as soon as possible, before anyone else can see them.
Anyway, good luck on experimenting with your static analyzer! If I sound ranty, it's because I've been playing around with an assembly language environment (MIT's BSim) and this diaperless environment is SO MUCH better than these other languages I've messed around with save for lisp.
> My first impulse is to agree, but the biggest (generally agreed upon) > benefit of static typing is that type errors are caught at compile-time, and > that benefit can only be reaped by restricting yourself from doing anything > that would violate the system.
This is a case where a bunch of people agreeing doesn't count for anything. You wish to do an innovative thing, creating a static lisp. Therefore you can stand a little zigging while others zag.
* Tayssir John Gabbour | /Static analysis does not mean it must run at compiletime./
Actually, that it run at compile time is the definition of «static» -- it requires no dynamic (= run-time) information.
| However, there is this insane presumption, orthogonal to static | analysis, that says we must run screaming from errors with our hands | over our ears. I don't think this is a fault in anyone, just our | byzantine languages and educations that pressure us into being macho | and hiding our faults as soon as possible, before anyone else can see | them.
Well said. :)
-- Erik Naggum | Oslo, Norway 2004-026
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
"sajiimori" <myusern...@hotmail.com> wrote in message <news:BA1Rb.27109$1e.4522@newsread2.news.pas.earthlink.net>... > You folks sure are touchy -- I didn't even say that I want static or > implicit typing. I thought it would take at least a few posts before the > rudeness began.
You're wrong here. Erik was very polite. Did you notice most people presume software people are rude by being very exacting with peers, almost to the point of triviality?
And it's not just "software people"; you'll find it among people who care about what they do. Or social retards, but I'm talking generally and there are exceptions.
sm> If I were still running a Unix, I'd check out CMUCL -- as it is, I've only sm> seen CLISP and Corman, neither of which catch type errors at compile time. sm> :( Would CMUCL warn about this during compile-time? If not, do you think sm> it should? sm> sm> (defun x-plus-y (x y) sm> (+ x y)) sm> sm> (defun test () sm> (x-plus-y 5 "asdf"))
in its default mode of operation, the CMUCL compiler assumes that a function may be redefined at runtime (unless it is declared to be inlineable). Therefore, it doesn't generate a warning when compiling code like this.
However, CMUCL's block-compilation mechanism allows you to tell the compiler that functions won't be redefined at runtime, which gives you semantics closer to static languages like C/Java/ML. There are a number of ways to obtain block-compilation (see the CMUCL User's Manual); one of them is to provide extra arguments to COMPILE-FILE.
,---- | CL-USER> (compile-file "err" :block-compile t :entry-points '(test)) | ; File: /tmp/err.lisp | ; In: defun x-plus-y | ; (+ x y) | ; Warning: Lisp error during constant folding: | ; Argument y is not a number: "asdf". `----