Domain: franz.com
Stories and comments across the archive that link to franz.com.
Stories · 3
-
Kent M. Pitman's Second Wind
Kent M. Pitman has already given you his first 11 answers to the questions you asked him about Lisp, Scheme, the creation of programming standards, and much more -- below are his answers to another eight (starting with answer #12). Thanks again, Kent.12) Good texts for learning Scheme?
by drenehtsralI have recently been working on learning Scheme in my spare time, with the eventual goal of writing a scheme based scripting system to run the guts of a massive adventure game/graphical mud sort of system, everything from environment simulation (predator/prey cycles, etc...) to 3d models (i.e. models will be geometry glued together by scripts so you could have trees that by a random seed and a growth level variable have grown over time and are unique to provide interresting landscape features). Scheme is appealing because it's simple, powerful, and adapts well to the idea of a threaded interpreter.
To further my goal of learning Scheme inside and out, I've been reading "The Little Schemer," as well as "Structure and Interpretation of Computer Programs." Do you have any other recommendations for good Scheme programming texts?
Kent M. Pitman: You can get a list of textbooks from Schemers website. If you can articulate a particular need or preference that you think should help narrow down the many available choices, I'd suggest posting a more specific inquiry to the comp.lang.scheme newsgroup.
13) Overlooked practical aspects of Lisp
by hdingWhy do you think that people so often overlook many of the wonderful things in Common Lisp such as unwind-protect, the whole condition system (which you are of course closely associated with), and so on - things that make it very useful for day-to-day programming, and are there any such things that you'd particularly highlight, or conversely that you wish had become part of the standard but did not.
Incidentally, thank you for all of the insight so generously and regularly poured forth in comp.lang.lisp.
KMP: Well, people program with tools that are familiar to them. Unless Common Lisp is someone's first language, it'd be easy for them to overlook the things it contains that are not like the things they're familiar with. There's a certain irony here because often the reason people will leave a language for another language is that they've reached the limits of what they can do with the first language and they need more power. So you'd expect that they'd aggressively look for features of the new language that were different than the things they've used before. And probably some do. But you're right that others cling to the safety and familiarity of the operators they could just as well have found in the old language they left behind, and so in the process they miss out on what the language can offer them.
Fortunately, unwind-protect is finally (pardon the pun) present in Java. And some hints of the Common Lisp condition system made it into Java as well. So probably people who come to Common Lisp from Java will be inclined to seek out those capabilities. But there's a lot of other stuff there and I hope new users will indulge their curiosity and take the time to explore.
As to what we should have in the language, the main omission of note is some sort of system definition tool (the in-Lisp analog of make). It was a shame that we did a feature-freeze on ANSI Common Lisp in 1988 but didn't get the standard out until 1994, and the suggestion of including such a tool didn't come until the after-freeze period. All vendors offer such a facility, but programs would be more portable if there were a uniform solution.
There are also quite a number of things about Common Lisp that are available in the same or similar forms in nearly all implementations. Multi-tasking, sockets, database access, external function call, windowing, and so on. It wouldn't be bad to have included any of these, but the fact is that they weren't ready for standarization in 1988. At this point, though, I think other mechanisms than standards are the right way to proceed.
The Lisp community used to expect the delivery mechanism for new functionality to be a new language spec. But that requires working through consensus standards bodies. The problem is that, by their nature, standards bodies are synchronization mechanisms. The problem with synchronization mechanisms in a massively parallel world is that they slow things down. The world is not going to wait for us to slow down, so I think we need to evolve mechanisms that will keep up better with a degree of pace that is externally dictated.
I think this is an area where Lisp as a community has been slow to respond. There need to be community mechanisms for sharing the many great commercial and private packages people have been creating in Lisp, so that we can properly reap the cross-product benefits of our community's productivity. I see evidence that this is changing. The Common Lisp Open Code Collection (CLOCC) is one such mechanism that addresses open source code. I'd like to see similar mechanisms arise for the exchange of proprietary products as well.
As to my posts on the comp.lang.lisp newsgroup, thank you. I'm glad you enjoy them. Frankly, I always consider it a victory to hear I haven't bored everyone to death. In background I've been working on putting together several books on Lisp, but one never quite knows if one will finish such things. I regard comp.lang.lisp as a kind of insurance policy, assuring that at least some piece of what I have seen and done in my career gets transferred from individual memory to global group memory.
I think preserving individual experiences for history is quite important. In the future, this will happen naturally due to logs kept by online collaboration tools. But I'm especially worried about the records of what happened between about 1960 (the birth of programming languages) and 1994 (the birth of the web). Most of everything in that time range is recorded on paper and will eventually be lost. Looking back from the future, I expect it to be as confusing to figure out how the information society was born as it is to look back in a telescope to see the birth of the Universe. You'll get very close, but then you'll get to a point where you can see nothing. The informational big bang. I've been working on webbing all of my old hardcopy papers, and I hope others of that era will commit to doing the same.
14) Lisp - Scheme - ML
by Tom7I know a lot of big academic (erstwhile) lisp shops, such as CMU, have transitioned away from lisp to ML [standardml.org] and relatives [inria.fr]. Some of the reasons we might give are:
- Sophisticated type systems, catching most bugs before your program is run, ensuring safety, etc.
- Much more efficient (http://www.bagley.org/~doug/shootout/craps.shtml), partly due to compilation strategies using types
- Increased modularity and abstraction
- Pattern matching, (subjectively) more natural syntax
In fact, I'm one of those people. I've been scoffed at by lisp fans, but most had never used ML. But I have an open mind, so, in the face of more "modern" languages, what advantages do lisp and scheme offer? Do you think that these advantages are fundamentally impossible to achieve in a typed setting?
KMP: First, I assume by "typed" you mean "statically typed." I think of Lisp as "dynamically typed." I think of most machine languages as "untyped." I've heard statically typed languages sometimes called strongly typed, and I sometimes use this terminology myself out of habit, but I've grown to dislike it because it seems to me that the issue of strength ought to refer to whether you check types, not when you do. The terms "static" and "dynamic" seem to me to better get to the heart of the matter.
To quote Abraham Lincoln, admittedly somewhat out of context, "People who like this sort of thing will find this the sort of thing they like." So to somewhat flippantly re-interpret Lincoln's remarks in a modern context, applying perhaps just a bit of obligatory political spin to the result: The fact that functional languages appeal to people who like functional languages is not a proof that functional languages are of general purpose appeal.
I think the real reason that CMU (or any university with a grant-based funding model) changed its direction is good sources of funding in research depend on saying you're doing something "new and different." Such a shift doesn't imply that the thing left behind wasn't "tried and true," but only that "tried and true" is not what gets research dollars. Research must constantly stir the mix, but that doesn't imply obsolescence to what came before. So don't read too much into that.
Answering each of your points in detail might require a whole article, but I'll touch on each in brief:
- Sophisticated type systems, catching most bugs before your
program is run, ensuring safety, etc. Much more efficient partly due to
compilation strategies using types.
Actually, it's funny that you both mention the CMU project and then make this comment. Before moving away from Common Lisp, the CMU crowd was successful in demonstrating to the Lisp community's satisfaction that there were enormous opportunities offered by the Common Lisp language design in terms of type inferencing that still today go untapped by implementations. This is really a market issue, not a language design issue. The fact is that although other languages do a lot more type inferencing, vendors are not getting huge numbers of bug reports saying that better type inferencing is what stands between programmers and the commercial success of their product. Over time, I think you'll see more and more interesting type analysis done, but such work is always balanced against other needs of users, such as CORBA, COM, RMI, and web interfaces, for example, such as UI toolkits and debugging options. When I observe, as I often do, that languages are political parties, this is what I mean. They are each responsive not to the needs of the world, but to the needs of their constituencies. And the Lisp constituency, while it is not oblivious to the value of type inferencing, does not see that issue as its number one priority.
- Increased modularity and abstraction.
This is quite a multidimensional space. I think Lisp provides great opportunities for modularity and abstraction that other languages do not. And yet, there are sometimes things I can't abstract as well as I wish. An example of a minor omission: Common Lisp's CLOS doesn't do protocol abstraction as well as Zetalisp's New Flavors; among other things, one can't declare that certain unimplemented methods are required. But with the use of the macro system and the Meta-Object Protocol (MOP), one can add this kind of thing. Further, the package system is missing certain kinds of inheritance capabilities I've often wished for, but I recently sat down and did the work of writing my own versions of defpackage for my own use, adding the capabilities I wanted in a way that my own tools can use, and I had no difficulty. For the most part, I've found the limitations of Common Lisp's abstraction capabilites to be incidental, and not deep, and I've found its syntactic reorganization capabilities more than capable of making up for it.
-
Pattern matching.
I think you're right that Lisp doesn't do pattern matching. Whether or not that's a good or bad thing is subjective. I think there are people who like pattern matching and people who don't. In fairness to Lisp, though, on the few occasions in my career where I've felt a strong need for pattern matching, I've been able to implement it easily. And, importantly, Lisp's syntactic adaptability has allowed me to make my personal implementation look as natural in the programs I write as if it were natively provided by the language; most other languages don't give me the syntactic control to be able to add new functionality in a way that feels appropriate to the language. So personally, I don't find this a strong negative; rather, I see it as an opportunity for you to create a layered library that supports the needs of yourself and others like you.
-
(Subjectively) more natural syntax.
I don't think you can make the case that much of any language has "natural" syntax. COBOL and HyperTalk gave this the fairest shot and there's a big difference even between them and any natural language. I personally find Lisp syntax remarkably natural in that it focuses on symbols that you could say out loud, marking them minimally to indicate grouping. Other languages contain lots of special-purpose markers like commas, semicolons, asterisks, and braces/brackets/parens that are used in quite nitpicky ways. All this to say that you're right on this one: it's subjective. And as such, I hope I can fairly dismiss this as an even draw.
15) Lisp in Mathematics Programming
by An Anonymous CowardGregory Chaitin has a book called "The Limits of Mathematics." In it he claims that mathematicians should love Lisp because Lisp is basically set theory, and all mathematicians love set theory. I wholeheartedly agree with this, one only needs to look at Chaitin's Lisp programs to realize how quickly and succinctly one can arrive at astonishing incompleteness results in mathematics. So we know Lisp is great for stuff like this, really researching a mathematical subject. Do you see Lisp continuing in this direction, showing and discovering theorems, or will it move into industry? Or has it moved into industry, and we just don't know it? Do the likes of NASA and JPL use Lisp and Scheme religiously? I would bet so.
KMP: Lisp may have started out as a way of addressing abstract topics like math (logic, calculus, prime numbers, etc.) and artificial intelligence, but it long ago made the transition to commercial applications. Both Scheme and Common Lisp have been and continue to be used in real-world applications that might surprise you. These include (but are certainly not limited to) applications in airline scheduling, commercial database manipulation, computer operating systems, bioengineering, web services, document format translation, and, yes, even space exploration. Franz, Inc. has created quite a nice page of Lisp success stories that I think expand on this much better than I could in the space I've allowed myself to answer this question. And speaking of NASA/JPL, they did a comparative study of Lisp vs Java and C++ that some might find interesting.
16) Scheme in CS
by An Anonymous CowardIt seems many of the more popular CS programs in the world use Scheme as a teaching language. A lot of times, students complain about this, saying they'd prefer to learn about C or another language that is considered "apt for industry." I used to be like this too, but have now discovered the error of my thinking. How have you convinced others that while the latest programs might not be written in Scheme, that it is worth a student's time to learn Scheme. Many seem stuck to the point that if they won't use it outside of school, they shouldn't learn it. How can we convince them otherwise, to become scholarly citizens instead of drones?
KMP: I think the thing to explain to a student is that the world is ever changing and that one cannot put ones eggs all in one basket. Furthermore, modern environments are often quite heterogeneous, with different languages and systems being used together cooperatively. Especially for a CS student, who often has the luxury of time that a person in the job world does not, I think it's worth taking time to learn as many different languages as possible. This not only exposes the students to alternate ways of thinking, but it also prepares the student to quickly change modes of thought or languages of expression later. Once on the job, one often can't afford the ramp-up time to learn a new language at the point it becomes necessary to use. Better to already know it and just have to "brush up".
One is much more likely to consider alternative approaches if one has a sense of what is involved in them; it's very easy to fear the unknown, even when the unknown might be of great help. So get to know as many things as you can while you can. Common Lisp and Scheme, which I regard as two very different languages, by the way, should definitely be among the things every student studies. But they should not be the only things the person studies. Like it or not, there is a lot the professional programmer needs to know to be really successful not just tomorrow, but for a lifetime.
As Oliver Wendell Holmes is often quoted as saying, "A mind stretched to a new idea never returns to its original dimensions." In order to stretch a student's mind, I recommend they make a list of "kinds of languages" and then learn as many different kinds as they can. Here are some that come to mind, though I'm sure others with different experience than me might reasonably contribute still others.
- A block-structured language, such as Algol or Pascal or Scheme.
- A line-oriented language, such as Fortran or BASIC.
- A rule-based logic language, such as Prolog or EMYCIN.
- An Englishy language such as HyperTalk or Cobol.
- A "stack" language such as PostScript.
- A "line noise" language (heavy emphasis on one-letter operators) like APL or Teco.
- A dynamic object-oriented language, such as Common Lisp or Smalltalk .
- A strongly-typed, statically analyzed language such as ML or Haskell.
- A dynamically-typed functional programming language, such as Scheme.
- A string or macro processing language, such as Perl or m4 or TeX or Teco.
- A database access language, such as SQL.
- An abstract high-level, assembly language, such as Java.
- A concrete high-level, assembly language, such as C.
- A low-level, traditional assembly language.
- A scripting language, such as Javascript.
- An interface-definition language such as Visual Basic, HyperTalk, or Javascript.
- A document-structuring language such as XSL or TeX.
- A language with a modern error system, such as Common Lisp or Dylan.
- A reflective/introspective language such as Common Lisp or Java.
- A symbolic programming language, such as Common Lisp or Scheme.
- A security-oriented language, such as Java or MOO.
- A language where both programs and data are fully persistent, such as MOO or HyperTalk.
17) A question for Kent
by MarkusQDo you have a maclisp manual I could borrow?
KMP:For those not familiar with Maclisp, it's a defunct dialect of Lisp that predated and strongly influenced the design of Common Lisp.
I've been working on webbing The Revised Maclisp Manual, which I had published on paper back in the early 1980's. It's not quite ready to go out yet, but should finally be ready sometime in the not terribly distant future. Probably a month or two. Watch the site maclisp.info for more information.
18) Open Implementations
by Martin PomijeWhat is your opinion of the idea of Open Implementations from Gregor Kiczales? Do you think that his idea could help Lisp be more widely used?
You can see him giving a lecture about this idea here. [microsoft.com] The video is only available in Windows Media format on this site.
KMP: I hadn't seen Gregor Kiczales's talk on Open Implementations, so I enjoyed watching it. Thanks for the pointer!
The talk made me think back to various related ideas I've seen batted around for a long time, the earliest of which that I can recall is a short paper on something called "Capsules" (an object system where classes were allowed to have multiple implementations) by Richard Zippel back in the late 1970s or early 1980s at MIT. Often, especially in a university environment, people will make up such a concept, bat it around for a bit, and then go on to something else. There are some very interesting ideas there and I'm glad to see that they're being pursued seriously, especially by someone as thoughtful and talented as I know Gregor to be.
As a formalized area of study, this topic of "aspect-oriented programming" is new to me. It reuses some old ideas in new ways, and introduces some new ones along with it. I'm only just barely becoming conversant in the terminology, so I can't really speak to it from a theoretical point of view. But it looks promising. And from a practical point of view, I can note that I'm getting daily on-the-job training in it through my consulting relationship with The Software Smith. They're using Lisp as a vehicle to apply the principles of aspect-oriented programming, and the results they get are quite spectacular.
19) What was up with CLisp's "loop" form?
by JaysonDid you can have anything to do or know who had anything to do with the "loop" form in Common Lisp? Why does it look and feel just like a FOR loop on C (from the Graham book):
(loop for x = 8 then (/x 2)
until (< x 1)
do (princ x))This is one of by biggest minor nags about CLisp and I am very curious what was going through the committee's collective head. Didn't anybody balk at this enough to at least get the syntax cleaned up?
KMP: The example you cite is quite simplistic and if this were the only reason for using LOOP, we wouldn't have it. Lisp has a number of other iteration operators for doing simple loops like this. However, the reason for using LOOP is that it can represent much more complicated arrangements of iteration paths and collection techniques. I used to grumble a lot myself about how "un-Lispy" LOOP seemed, but over time I come to the belief that the benefits outweigh the costs. A loop like this:
(loop for x from 0
for y in some-list
when (good-result? y)
collect (list x y))
is easy to write and maintain, and much easier to explain than the equivalent, but more Lispy:
(do ((x 0 (+ x 1))
(y-list some-list (cdr y-list))
(result '()))
((null y)
(nreverse result))
(let ((y (first y-list)))
(when (good-result? y)
(push (list x y) result))))
The Common Lisp community likes to offer the traditional Lispy notations for places where they enhance readability, but we also offer alternative notations for situations where we've learned there's a call for it. We leave the choice of which style to use up to the individual taste of the programmer. Common Lisp is not a minimalist language offering only one way to do things or rigidly attempting to force people into a single programming paradigm.
By the way, this is a fundamental difference between the ANSI Common Lisp design philosophy and the Scheme design philosophy. The introduction to the Scheme specification states:
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today.
By contrast, the charter for X3J13, the group that designed ANSI Common Lisp, stated the following in the X3J13 charter:It will codify existing practice, provide additional features to facilitate portability of code among diverse implementations, and establish normative Common Lisp programming practice. The committee will begin with the language described in Common Lisp: The Language by Guy L. Steele Jr. (Digital Press, 1984), which is the current de facto standard for Common Lisp. Whenever there is a proposal for the standard to differ from Common Lisp: The Language, the committee shall weigh both future costs of adopting (or not adopting) a change and costs of conversion of existing code. Aesthetic criteria shall be a subordinate consideration.
In other words, the Scheme community is a very conservative community that is highly focused on keeping its language specification as highly aesthetic and minimal in size as possible. By contrast, the Common Lisp community is an industrial standard that is concerned with messier issues of compatibility, portability, and commercial need; while the Common Lisp community cares about aesthetics, it does not allow aesthetics to dominate practicality as a design criterion.
The relevance of this here is that the Lisp family of languages is made up of a number of smaller communities who share a few core ideas, but really have some very divergent points of view. Each is worthy of study in its own right. One should not, having looked at Scheme, assume they have good intuitions about Common Lisp, nor vice versa.
-
Kent M. Pitman's Second Wind
Kent M. Pitman has already given you his first 11 answers to the questions you asked him about Lisp, Scheme, the creation of programming standards, and much more -- below are his answers to another eight (starting with answer #12). Thanks again, Kent.12) Good texts for learning Scheme?
by drenehtsralI have recently been working on learning Scheme in my spare time, with the eventual goal of writing a scheme based scripting system to run the guts of a massive adventure game/graphical mud sort of system, everything from environment simulation (predator/prey cycles, etc...) to 3d models (i.e. models will be geometry glued together by scripts so you could have trees that by a random seed and a growth level variable have grown over time and are unique to provide interresting landscape features). Scheme is appealing because it's simple, powerful, and adapts well to the idea of a threaded interpreter.
To further my goal of learning Scheme inside and out, I've been reading "The Little Schemer," as well as "Structure and Interpretation of Computer Programs." Do you have any other recommendations for good Scheme programming texts?
Kent M. Pitman: You can get a list of textbooks from Schemers website. If you can articulate a particular need or preference that you think should help narrow down the many available choices, I'd suggest posting a more specific inquiry to the comp.lang.scheme newsgroup.
13) Overlooked practical aspects of Lisp
by hdingWhy do you think that people so often overlook many of the wonderful things in Common Lisp such as unwind-protect, the whole condition system (which you are of course closely associated with), and so on - things that make it very useful for day-to-day programming, and are there any such things that you'd particularly highlight, or conversely that you wish had become part of the standard but did not.
Incidentally, thank you for all of the insight so generously and regularly poured forth in comp.lang.lisp.
KMP: Well, people program with tools that are familiar to them. Unless Common Lisp is someone's first language, it'd be easy for them to overlook the things it contains that are not like the things they're familiar with. There's a certain irony here because often the reason people will leave a language for another language is that they've reached the limits of what they can do with the first language and they need more power. So you'd expect that they'd aggressively look for features of the new language that were different than the things they've used before. And probably some do. But you're right that others cling to the safety and familiarity of the operators they could just as well have found in the old language they left behind, and so in the process they miss out on what the language can offer them.
Fortunately, unwind-protect is finally (pardon the pun) present in Java. And some hints of the Common Lisp condition system made it into Java as well. So probably people who come to Common Lisp from Java will be inclined to seek out those capabilities. But there's a lot of other stuff there and I hope new users will indulge their curiosity and take the time to explore.
As to what we should have in the language, the main omission of note is some sort of system definition tool (the in-Lisp analog of make). It was a shame that we did a feature-freeze on ANSI Common Lisp in 1988 but didn't get the standard out until 1994, and the suggestion of including such a tool didn't come until the after-freeze period. All vendors offer such a facility, but programs would be more portable if there were a uniform solution.
There are also quite a number of things about Common Lisp that are available in the same or similar forms in nearly all implementations. Multi-tasking, sockets, database access, external function call, windowing, and so on. It wouldn't be bad to have included any of these, but the fact is that they weren't ready for standarization in 1988. At this point, though, I think other mechanisms than standards are the right way to proceed.
The Lisp community used to expect the delivery mechanism for new functionality to be a new language spec. But that requires working through consensus standards bodies. The problem is that, by their nature, standards bodies are synchronization mechanisms. The problem with synchronization mechanisms in a massively parallel world is that they slow things down. The world is not going to wait for us to slow down, so I think we need to evolve mechanisms that will keep up better with a degree of pace that is externally dictated.
I think this is an area where Lisp as a community has been slow to respond. There need to be community mechanisms for sharing the many great commercial and private packages people have been creating in Lisp, so that we can properly reap the cross-product benefits of our community's productivity. I see evidence that this is changing. The Common Lisp Open Code Collection (CLOCC) is one such mechanism that addresses open source code. I'd like to see similar mechanisms arise for the exchange of proprietary products as well.
As to my posts on the comp.lang.lisp newsgroup, thank you. I'm glad you enjoy them. Frankly, I always consider it a victory to hear I haven't bored everyone to death. In background I've been working on putting together several books on Lisp, but one never quite knows if one will finish such things. I regard comp.lang.lisp as a kind of insurance policy, assuring that at least some piece of what I have seen and done in my career gets transferred from individual memory to global group memory.
I think preserving individual experiences for history is quite important. In the future, this will happen naturally due to logs kept by online collaboration tools. But I'm especially worried about the records of what happened between about 1960 (the birth of programming languages) and 1994 (the birth of the web). Most of everything in that time range is recorded on paper and will eventually be lost. Looking back from the future, I expect it to be as confusing to figure out how the information society was born as it is to look back in a telescope to see the birth of the Universe. You'll get very close, but then you'll get to a point where you can see nothing. The informational big bang. I've been working on webbing all of my old hardcopy papers, and I hope others of that era will commit to doing the same.
14) Lisp - Scheme - ML
by Tom7I know a lot of big academic (erstwhile) lisp shops, such as CMU, have transitioned away from lisp to ML [standardml.org] and relatives [inria.fr]. Some of the reasons we might give are:
- Sophisticated type systems, catching most bugs before your program is run, ensuring safety, etc.
- Much more efficient (http://www.bagley.org/~doug/shootout/craps.shtml), partly due to compilation strategies using types
- Increased modularity and abstraction
- Pattern matching, (subjectively) more natural syntax
In fact, I'm one of those people. I've been scoffed at by lisp fans, but most had never used ML. But I have an open mind, so, in the face of more "modern" languages, what advantages do lisp and scheme offer? Do you think that these advantages are fundamentally impossible to achieve in a typed setting?
KMP: First, I assume by "typed" you mean "statically typed." I think of Lisp as "dynamically typed." I think of most machine languages as "untyped." I've heard statically typed languages sometimes called strongly typed, and I sometimes use this terminology myself out of habit, but I've grown to dislike it because it seems to me that the issue of strength ought to refer to whether you check types, not when you do. The terms "static" and "dynamic" seem to me to better get to the heart of the matter.
To quote Abraham Lincoln, admittedly somewhat out of context, "People who like this sort of thing will find this the sort of thing they like." So to somewhat flippantly re-interpret Lincoln's remarks in a modern context, applying perhaps just a bit of obligatory political spin to the result: The fact that functional languages appeal to people who like functional languages is not a proof that functional languages are of general purpose appeal.
I think the real reason that CMU (or any university with a grant-based funding model) changed its direction is good sources of funding in research depend on saying you're doing something "new and different." Such a shift doesn't imply that the thing left behind wasn't "tried and true," but only that "tried and true" is not what gets research dollars. Research must constantly stir the mix, but that doesn't imply obsolescence to what came before. So don't read too much into that.
Answering each of your points in detail might require a whole article, but I'll touch on each in brief:
- Sophisticated type systems, catching most bugs before your
program is run, ensuring safety, etc. Much more efficient partly due to
compilation strategies using types.
Actually, it's funny that you both mention the CMU project and then make this comment. Before moving away from Common Lisp, the CMU crowd was successful in demonstrating to the Lisp community's satisfaction that there were enormous opportunities offered by the Common Lisp language design in terms of type inferencing that still today go untapped by implementations. This is really a market issue, not a language design issue. The fact is that although other languages do a lot more type inferencing, vendors are not getting huge numbers of bug reports saying that better type inferencing is what stands between programmers and the commercial success of their product. Over time, I think you'll see more and more interesting type analysis done, but such work is always balanced against other needs of users, such as CORBA, COM, RMI, and web interfaces, for example, such as UI toolkits and debugging options. When I observe, as I often do, that languages are political parties, this is what I mean. They are each responsive not to the needs of the world, but to the needs of their constituencies. And the Lisp constituency, while it is not oblivious to the value of type inferencing, does not see that issue as its number one priority.
- Increased modularity and abstraction.
This is quite a multidimensional space. I think Lisp provides great opportunities for modularity and abstraction that other languages do not. And yet, there are sometimes things I can't abstract as well as I wish. An example of a minor omission: Common Lisp's CLOS doesn't do protocol abstraction as well as Zetalisp's New Flavors; among other things, one can't declare that certain unimplemented methods are required. But with the use of the macro system and the Meta-Object Protocol (MOP), one can add this kind of thing. Further, the package system is missing certain kinds of inheritance capabilities I've often wished for, but I recently sat down and did the work of writing my own versions of defpackage for my own use, adding the capabilities I wanted in a way that my own tools can use, and I had no difficulty. For the most part, I've found the limitations of Common Lisp's abstraction capabilites to be incidental, and not deep, and I've found its syntactic reorganization capabilities more than capable of making up for it.
-
Pattern matching.
I think you're right that Lisp doesn't do pattern matching. Whether or not that's a good or bad thing is subjective. I think there are people who like pattern matching and people who don't. In fairness to Lisp, though, on the few occasions in my career where I've felt a strong need for pattern matching, I've been able to implement it easily. And, importantly, Lisp's syntactic adaptability has allowed me to make my personal implementation look as natural in the programs I write as if it were natively provided by the language; most other languages don't give me the syntactic control to be able to add new functionality in a way that feels appropriate to the language. So personally, I don't find this a strong negative; rather, I see it as an opportunity for you to create a layered library that supports the needs of yourself and others like you.
-
(Subjectively) more natural syntax.
I don't think you can make the case that much of any language has "natural" syntax. COBOL and HyperTalk gave this the fairest shot and there's a big difference even between them and any natural language. I personally find Lisp syntax remarkably natural in that it focuses on symbols that you could say out loud, marking them minimally to indicate grouping. Other languages contain lots of special-purpose markers like commas, semicolons, asterisks, and braces/brackets/parens that are used in quite nitpicky ways. All this to say that you're right on this one: it's subjective. And as such, I hope I can fairly dismiss this as an even draw.
15) Lisp in Mathematics Programming
by An Anonymous CowardGregory Chaitin has a book called "The Limits of Mathematics." In it he claims that mathematicians should love Lisp because Lisp is basically set theory, and all mathematicians love set theory. I wholeheartedly agree with this, one only needs to look at Chaitin's Lisp programs to realize how quickly and succinctly one can arrive at astonishing incompleteness results in mathematics. So we know Lisp is great for stuff like this, really researching a mathematical subject. Do you see Lisp continuing in this direction, showing and discovering theorems, or will it move into industry? Or has it moved into industry, and we just don't know it? Do the likes of NASA and JPL use Lisp and Scheme religiously? I would bet so.
KMP: Lisp may have started out as a way of addressing abstract topics like math (logic, calculus, prime numbers, etc.) and artificial intelligence, but it long ago made the transition to commercial applications. Both Scheme and Common Lisp have been and continue to be used in real-world applications that might surprise you. These include (but are certainly not limited to) applications in airline scheduling, commercial database manipulation, computer operating systems, bioengineering, web services, document format translation, and, yes, even space exploration. Franz, Inc. has created quite a nice page of Lisp success stories that I think expand on this much better than I could in the space I've allowed myself to answer this question. And speaking of NASA/JPL, they did a comparative study of Lisp vs Java and C++ that some might find interesting.
16) Scheme in CS
by An Anonymous CowardIt seems many of the more popular CS programs in the world use Scheme as a teaching language. A lot of times, students complain about this, saying they'd prefer to learn about C or another language that is considered "apt for industry." I used to be like this too, but have now discovered the error of my thinking. How have you convinced others that while the latest programs might not be written in Scheme, that it is worth a student's time to learn Scheme. Many seem stuck to the point that if they won't use it outside of school, they shouldn't learn it. How can we convince them otherwise, to become scholarly citizens instead of drones?
KMP: I think the thing to explain to a student is that the world is ever changing and that one cannot put ones eggs all in one basket. Furthermore, modern environments are often quite heterogeneous, with different languages and systems being used together cooperatively. Especially for a CS student, who often has the luxury of time that a person in the job world does not, I think it's worth taking time to learn as many different languages as possible. This not only exposes the students to alternate ways of thinking, but it also prepares the student to quickly change modes of thought or languages of expression later. Once on the job, one often can't afford the ramp-up time to learn a new language at the point it becomes necessary to use. Better to already know it and just have to "brush up".
One is much more likely to consider alternative approaches if one has a sense of what is involved in them; it's very easy to fear the unknown, even when the unknown might be of great help. So get to know as many things as you can while you can. Common Lisp and Scheme, which I regard as two very different languages, by the way, should definitely be among the things every student studies. But they should not be the only things the person studies. Like it or not, there is a lot the professional programmer needs to know to be really successful not just tomorrow, but for a lifetime.
As Oliver Wendell Holmes is often quoted as saying, "A mind stretched to a new idea never returns to its original dimensions." In order to stretch a student's mind, I recommend they make a list of "kinds of languages" and then learn as many different kinds as they can. Here are some that come to mind, though I'm sure others with different experience than me might reasonably contribute still others.
- A block-structured language, such as Algol or Pascal or Scheme.
- A line-oriented language, such as Fortran or BASIC.
- A rule-based logic language, such as Prolog or EMYCIN.
- An Englishy language such as HyperTalk or Cobol.
- A "stack" language such as PostScript.
- A "line noise" language (heavy emphasis on one-letter operators) like APL or Teco.
- A dynamic object-oriented language, such as Common Lisp or Smalltalk .
- A strongly-typed, statically analyzed language such as ML or Haskell.
- A dynamically-typed functional programming language, such as Scheme.
- A string or macro processing language, such as Perl or m4 or TeX or Teco.
- A database access language, such as SQL.
- An abstract high-level, assembly language, such as Java.
- A concrete high-level, assembly language, such as C.
- A low-level, traditional assembly language.
- A scripting language, such as Javascript.
- An interface-definition language such as Visual Basic, HyperTalk, or Javascript.
- A document-structuring language such as XSL or TeX.
- A language with a modern error system, such as Common Lisp or Dylan.
- A reflective/introspective language such as Common Lisp or Java.
- A symbolic programming language, such as Common Lisp or Scheme.
- A security-oriented language, such as Java or MOO.
- A language where both programs and data are fully persistent, such as MOO or HyperTalk.
17) A question for Kent
by MarkusQDo you have a maclisp manual I could borrow?
KMP:For those not familiar with Maclisp, it's a defunct dialect of Lisp that predated and strongly influenced the design of Common Lisp.
I've been working on webbing The Revised Maclisp Manual, which I had published on paper back in the early 1980's. It's not quite ready to go out yet, but should finally be ready sometime in the not terribly distant future. Probably a month or two. Watch the site maclisp.info for more information.
18) Open Implementations
by Martin PomijeWhat is your opinion of the idea of Open Implementations from Gregor Kiczales? Do you think that his idea could help Lisp be more widely used?
You can see him giving a lecture about this idea here. [microsoft.com] The video is only available in Windows Media format on this site.
KMP: I hadn't seen Gregor Kiczales's talk on Open Implementations, so I enjoyed watching it. Thanks for the pointer!
The talk made me think back to various related ideas I've seen batted around for a long time, the earliest of which that I can recall is a short paper on something called "Capsules" (an object system where classes were allowed to have multiple implementations) by Richard Zippel back in the late 1970s or early 1980s at MIT. Often, especially in a university environment, people will make up such a concept, bat it around for a bit, and then go on to something else. There are some very interesting ideas there and I'm glad to see that they're being pursued seriously, especially by someone as thoughtful and talented as I know Gregor to be.
As a formalized area of study, this topic of "aspect-oriented programming" is new to me. It reuses some old ideas in new ways, and introduces some new ones along with it. I'm only just barely becoming conversant in the terminology, so I can't really speak to it from a theoretical point of view. But it looks promising. And from a practical point of view, I can note that I'm getting daily on-the-job training in it through my consulting relationship with The Software Smith. They're using Lisp as a vehicle to apply the principles of aspect-oriented programming, and the results they get are quite spectacular.
19) What was up with CLisp's "loop" form?
by JaysonDid you can have anything to do or know who had anything to do with the "loop" form in Common Lisp? Why does it look and feel just like a FOR loop on C (from the Graham book):
(loop for x = 8 then (/x 2)
until (< x 1)
do (princ x))This is one of by biggest minor nags about CLisp and I am very curious what was going through the committee's collective head. Didn't anybody balk at this enough to at least get the syntax cleaned up?
KMP: The example you cite is quite simplistic and if this were the only reason for using LOOP, we wouldn't have it. Lisp has a number of other iteration operators for doing simple loops like this. However, the reason for using LOOP is that it can represent much more complicated arrangements of iteration paths and collection techniques. I used to grumble a lot myself about how "un-Lispy" LOOP seemed, but over time I come to the belief that the benefits outweigh the costs. A loop like this:
(loop for x from 0
for y in some-list
when (good-result? y)
collect (list x y))
is easy to write and maintain, and much easier to explain than the equivalent, but more Lispy:
(do ((x 0 (+ x 1))
(y-list some-list (cdr y-list))
(result '()))
((null y)
(nreverse result))
(let ((y (first y-list)))
(when (good-result? y)
(push (list x y) result))))
The Common Lisp community likes to offer the traditional Lispy notations for places where they enhance readability, but we also offer alternative notations for situations where we've learned there's a call for it. We leave the choice of which style to use up to the individual taste of the programmer. Common Lisp is not a minimalist language offering only one way to do things or rigidly attempting to force people into a single programming paradigm.
By the way, this is a fundamental difference between the ANSI Common Lisp design philosophy and the Scheme design philosophy. The introduction to the Scheme specification states:
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today.
By contrast, the charter for X3J13, the group that designed ANSI Common Lisp, stated the following in the X3J13 charter:It will codify existing practice, provide additional features to facilitate portability of code among diverse implementations, and establish normative Common Lisp programming practice. The committee will begin with the language described in Common Lisp: The Language by Guy L. Steele Jr. (Digital Press, 1984), which is the current de facto standard for Common Lisp. Whenever there is a proposal for the standard to differ from Common Lisp: The Language, the committee shall weigh both future costs of adopting (or not adopting) a change and costs of conversion of existing code. Aesthetic criteria shall be a subordinate consideration.
In other words, the Scheme community is a very conservative community that is highly focused on keeping its language specification as highly aesthetic and minimal in size as possible. By contrast, the Common Lisp community is an industrial standard that is concerned with messier issues of compatibility, portability, and commercial need; while the Common Lisp community cares about aesthetics, it does not allow aesthetics to dominate practicality as a design criterion.
The relevance of this here is that the Lisp family of languages is made up of a number of smaller communities who share a few core ideas, but really have some very divergent points of view. Each is worthy of study in its own right. One should not, having looked at Scheme, assume they have good intuitions about Common Lisp, nor vice versa.
-
Kent M. Pitman Answers On Lisp And Much More
A few weeks ago, you asked Kent M. Pitman about Lisp, Scheme, standards, and other things -- He's answered your questions below, at length. At such length, in fact, that only the first eleven of his answers are shown below -- expect more shortly! Thanks, Kent.1) (just one thing (I) want to (know))?
by An Anonymous Coward
((
What (
(is) with (all)
) of (the) ()s?
)
Hmmm?
)
Kent M. Pitman: This question actually got scored down to -1 and marked as a troll question, but I fished it out of the barrel and restored it because everyone asks and I might as well confront the issue head-on.
Ironically it's non-Lisp languages that allow and encourage you to put ()'s in any place you want, as if there were no meaning to the introduction of gratuitous paren groups.
3+(2*5)+7 means the same thing in an algebraic language as does 3+2*5+7. In Lisp, we write:
(+ 3 (* 2 5) 7)
This shows you the structure and means you never have to learn obscure precedence rules that make expressions like -3! confusing in algebraic languages, where you must learn whether it means (-3)! or -(3!). In Lisp, the parens would show you immediately that (factorial -3) or (- (factorial 3)) was intended.
The thing I personally like about (+ (* 2 y) x) rather than 2*y+x is that it simplifies my editing. I'm a touch-typist and I use the emacs commands to go forward and backward over expressions, to swap expressions, and to delete expressions very heavily. And I don't have to reach for the mouse to manipulate large, complex expressions because they are paren-bounded. If I put the cursor at the head of 2*y+x and say "go forward an expression", ought this go forward over 2, 2*y, or 2*y+x? Having different editor commands to move across a sum, a product, etc. would be unwieldy. Yet without that, I don't see how the editor would know. In Lisp, there can't be any ambiguity because every sub-expression has its own start character, so a single notion of "the expression in front of the cursor" or "the expression after the cursor" suffices.
This, by the way, also answers the question of why we don't write foo(x) and instead write (foo x). In Lisp notation, foo is an expression. In the expression (foo x), it's a subexpression, so it's enclosed within it. Were it outside, a text editor would not be sure if foo(x) were one expression (a function call) or two expressions (the symbol foo followed by the list (x)). That would make going forward over 'one expression' ambiguous when at the start of foo(x). Should the cursor end up after the foo or after the (x)? In other words, The natural purpose of parentheses is to enclose things, so that's what Lisp uses them for. Avoiding ambiguity is critical to the writing of correct "keyboard macros" in Emacs, where I might interactively write a program to do a lot of code transformations quickly. In an algebraic language, such keyboard macros can be much harder to write robustly.
2) It's not just me is it?
by demo9orgonAfter trying to "self-learn" lisp in the 80's I get this physical reaction to the word "lambda"...a cold sweat combined with the involuntary retraction of my testicles to a protected location in my abdomen (damn unpleasant shit)...I usually avoid that second one by mentally going through the mechanics of "hello world" in C, or any half-a-dozen other programming languages.
Lisp is one of those meta-languages you either learn or avoid. I write practical stuff all the time, daily in fact, and I've never had something that required the arcane stuff in LISP.
KMP: Actually, "hello world" in Lisp looks like this:
(defun hello-world ()
(write-line "Hello, World!"))
I don't know about you, but I find that pretty soothing.
And as to LAMBDA, one only needs use it when they find it useful. For example, after a while, one sometimes gets tired of writing a separate function where that function will only be used once, as in:
(defun sort-by-name (list)
(sort list #'name<))
(defun name<(name1 name2)
(or(string<(last-name name1) (last-name name2))
 (and (string= (last-name name1) (last-name name2))
(string< (first-name name1) (first-name name2)))))
so Lisp allows one to instead say:
(defun sort-by-name (list)
(sort list #'(lambda (name1 name2)
(or (string< (last-name name1) (last-name name2))
(and (string= (last-name name1) (last-name name2))
(string< (first-name name1) (first-name name2)))))))
Whether one actually does this is purely a personal preference. Some people like having separate named functions, some don't. Sometimes the separately named function might have a nonsensical name, though, and it's nicer not to have to invent a stupid name for a one-shot use.
Now, as to why it's called LAMBDA and not FUNCTION, that's just a piece of history. You get used to it. Toward that end, I'll offer a story that will perhaps help you put it in perspective:
Early in my not-yet career as a computer scientist, which is to say, while I was in high school, I lived in the Panama Canal Zone. Computers were not at all common there at the time. In fact, the place being entirely run by the US Government, there was some weird edict that said no one was allowed to own one so that they would all be centralized in the Comptroller's Office and not wasted in individual offices around the Zone. Our school had to bend the rules in order to get us a computer to study. So one thing I did while trying to learn about computers was to go downtown (out of the Canal Zone into Panama City, in the Republic of Panama) and visit a company there who did computer work. Of course, people there spoke Spanish, but fortunately I did, too. They showed me some of their code, and I was immediately struck by the fact that all the language keywords were in English.
"Doesn't that bother you?" I asked. But the person I was talking to was quite a thoughtful person and he immediately responded this way: "Do you know how to read music?" "A little," I said. "Have you seen the notations on music like forte, sotto voce, and so on?" I nodded. "Does it bother you that they are in Italian?" "No," I had to admit. His point was to make me see that it could be viewed as part of the charm and history of the notation. He was, perhaps, unusually forgiving. But this was in the late 1970s, when everyone who had access to computers was far too excited about just plain having them to care about subtle issues of whose culture got too much say in the design of a world-wide phenomenon.
So when today I look at the very few mysterious-looking terms like LAMBDA, CAR, and CDR that still linger untouched in modern Lisp's design, I think of them as I do those musical notations, conceptual links to a little piece of history that I'm just as happy not to see crushed by an overeager rush to regularize and homogenize the world--something the computer culture has done altogether too much of.
3) Interactively programmable applications
by divbyzero (divbyzero@hotmail.com)One of the primary reasons why Scheme and Lisp interest me is that they are well suited for making applications interactively programmable at runtime (Scheme especially, due to its small size). This is far more flexible and useful than applications which are only extensible through heavyweight, precompiled plugins. Since the Slashdot readership tends to be made up of people who are comfortable with programatic interfaces (unlike the general computer-using public), why do we not see more such applications?
KMP: I think it's just an issue of education, formal and otherwise. Without being explicitly guided, some people will try out all kinds of ways to do things, or invent them where they're not present. But many others will simply do what they have been taught to do without exploring the alternatives.
In the past, everything was about speed. Every instruction was precious. The focus was entirely on "micro" efficiency. People would examine the cost of being able to redefine something (which sometimes involves as much as following pointer indirection), and if there was a cycle lost, the game was over. Today, hardware cache and prefetch architectures can often hide such costs anyway, but even if they couldn't, processors run so fast that one has time to worry not only about micro efficiency but also macro efficiency--that is, "running smart", not just "running fast", as a way of assuring total efficiency.
A lot of people identify Lisp as a language that is "just good for Artificial Intelligence (AI)". Certainly Lisp is good for AI. But saying it is just good for AI misses the point. Lisp doesn't do AI. Lisp is a programming language. AI researchers program AI, and often their language of choice has been and continues to be Lisp. But the important thing is that AI researchers have been banging on the door of Lisp implementors for years, demanding the introduction and tuning of the features and constructs they need in order to get their work done. Lisp hasn't become a mere AI toolbox as a result of that. Rather, it has become a robust tool for addressing the world's most complex and vexing problems. The Lisp community has a long experience with supporting "intelligent programming", and with doing so efficiently.
Lisp's biggest problem in the past is probably that it hit its commercial peak too early, in the mid 1980s, before most computational problems the world was confronting were big enough to need the power Lisp had to offer. Those were the days of MacWrite and MacPaint and Lotus 1-2-3, and it just didn't make any difference whether one used Lisp or C for those. But for better or worse, the world has grown up around us, and the important problems of the day are a lot more complex. I think Lisp has a lot more to offer to the world of today than it ever did in the past.4) The standard process
by VPAs participant in the standardization process for Lisp, what are your thoughts on standards for programming languages? What would you like to see different in this process? And speaking of standards, what do you think about the RAND licensing issue and the W3C?
KMP: I think standards have served their time to provide a stable base for people to build on, but for the modern environment, they move way too slowly to keep pace with the speed of change in business. It took a long time to put the Common Lisp standard together. We began in 1986, finished work in 1994, and got the actual document to press just before the end of 1995. Getting community consensus on something that big really does take that long, and I think it was an exercise worth doing to create the stable base that we created, but for future evolution of the language, I think there needs to be another way with far less overhead.
I see standards as having two components: The first is to simply cast a name into concrete so that reference to that name will always have a clear meaning. The definition of ANSI Common Lisp, at least for 1994, is now permanently registered. Anyone who wants to can now conform to that definition and others will know exactly what they mean by that. The second component is to assert an informal consensus in the community that there is a single right way of doing things. This latter component may be useful for the foundation (to define the initial market space), but I'm not sure it's appropriate for the library level of the language.
For the base language, if 60% of the community wanted to do things one way and 40% another way, the 60% got to roll over the 40%, and 100% of the community was expected to do things in the way that won. But at the library level, if 60% want one library and 40% want another, I'd rather 100% of the community get what they want by having some people just do it one way and the rest of the people do it the other way. The Lisp community has not traditionally done things that way; they've sought consensus. The Scheme community has been even more conservative about this than the Common Lisp community, and as a result has even fewer standardized facilities than the Common Lisp community.
The Scheme community has moved to a more loose-knit approach to break the design deadlock brought on by the core language committee's consensus process through its Scheme Requests for Implementation (SRFI) process. The Common Lisp community hasn't got anything quite so organized yet, but I suspect will eventually evolve something similar.
As to the question of the W3C, I'm not a huge fan at the moment. At a prior employer, we had the opportunity to join, but the contract we'd have had to sign made it clear that votes among members were advisory only, and W3C itself could decide to override what people voted on. This, to me, is not a consensus body. Furthermore, although I think standards bodies like ANSI move in near glacial time, I don't think you can fix things by just shortening the times. True national and global consensus just takes time, and shortening timelines doesn't just make things move faster, it also disenfranchises people. While I use the existing HTML, CSS, XML, XSL, and other W3C guidelines, I don't feel they were created in a manner that I respect as proper consensus process. I think the process was insular and rushed.
Neither am I happy with the notion of processes involving Reasonable and Non-Discriminatory (RAND) fees being part of a standard; I think consensus standards should only involve royalty-free (RF) technologies. I think adherence to standards should not induce a baseline cost beyond the cost of creating the code so that the cost of compliance with standards can closely approach zero. If there is a profit to be made on the implementation of a standard, it should go to the implementor, not to a patent holder. Then again, while I'm a strong proponent of software copyright, I'm not at all a fan of software patents. Rather than seeing independent creation as infringement, I think independent creation should be contributory proof that an idea was more obvious than perhaps the patent office thought. I don't mind copyright because there are ways that one can demonstrate that one did not merely copy another's work, and independent creation is a defense.5) Advice to Aspirants
by An Anonymous CowardKent, I am one of the lucky ones who programs professionally in Common Lisp. I certainly appreciate your hard work and the hard work of everyone else who helped to bring us the ANSI standard - which serves to reify much of the esoteric knowledge the Lisp community has developed in the many years since the language was born.
While I do not need to be sold on Lisp, I know many people who do not fully appreciate the power of the language. To a large degree, this is due to misconceptions about the language. Specifically, there seem to be a number of what I would call 'cultural misconceptions'. Because many people have never worked in a tightly interactive development environment with incremental compilation, language-level introspection, and real code/data equivalence (not to mention the differences between CLOS and what the rest of the world seems to have come to believe is the God-given definition of 'object-oriented' programming) - they don't really 'get' what makes Lisp so special and so powerful. More to the point, because the logistics of developing and deploying applications in Lisp is different than what the typical c/c++/perl/java developer knows, the hurdle to even investigating or considering Lisp as a real possibility seems unnecessarily high.
Could you talk a bit about how those who have a feeling that Lisp might help them with their hard problems could go about bootstrapping their way into finding out? How would you suggest getting started? What is a reasonable set of tools for experimentation, and where should a beginner start with the language? (The standard is a big document!) Also, could you give an example of the type of problem space and style of application delivery that demonstrates that Lisp is more practical than many seem to believe?
KMP: Well, one thing to note is that there's very little overhead to just downloading an implementation and diving in. Not only do the major commercial vendors like Xanalys and Franz offer high quality, no-cost trial versions of their proprietary software, but there are quite a number of free (non-proprietary) versions of Lisp as well. Information about these, as well as much other useful information about Lisp, can be found at the Association of Lisp Users (ALU) web site. I've also recently purchased common-lisp.info, which I plan to maintain as a repository for information about Common Lisp; the site doesn't have a large base of information yet, but it does have a list of the problem spaces in which you might consider using Lisp.
The ANSI Common Lisp standard, effectively available in webbed form as the Common Lisp HyperSpec, is indeed a big document (about 16MB and having about 108 kilohyperlinks downloadable). I think it's fairly readable as standards go. But you're right that it takes some work to get through and it wasn't really intended as a tutorial.
The ALU web site will also have pointers to books and online tutorials about Lisp. Books by Paul Graham and Peter Norvig on the subject are very highly regarded. I think there is always room for more, and I'm working on several, at least one of which I hope to complete in the not too distant future; feedback from you and others is useful to me in understanding what areas most urgently require treatment.
One resource that some people might find useful is an article I wrote called Accelerating Hindsight: Lisp as a Vehicle for Rapid Prototyping. This article is intended primarily for a Lisp programmer audience, to help them articulate some of the ideas you've asked about to others. It was not intended to be read by the audience you'd like to convince mainly because it appeals periodically to Lispy notation that might not be familiar to them, but it may still be of interest to the adventurous non-Lisp reader.
As your project becomes more sophisticated, and evolves from a personal toy to a real commercial product, it also doesn't hurt to ask an expert for help. My company offers consulting services that include helping companies manage the transition into Lisp. One of my major clients, The Software Smith approached me on just such a basis and the result has been very exciting both for me (getting to help them improve their system) and, I think, for them (getting to see more of how Lisp is supposed to be used). I don't want to turn this interview into a huge advertisement, but people can contact me for more information. If I'm either not competent to help you or am too busy to help you, there's a very good chance I can refer you to someone else who can help you.
6) Language feature trickle-down
by WillWareI was a big Scheme/Lisp fan five or six years ago, but now I see most of my favorite Lisp-like language features available in Python, which is getting a huge amount of high-quality development mindshare these days. Some of the Lisp-ish features in Python that spring right to mind are functions as objects, closures, garbage collection, and dynamic-yet-strong typing, and convenient rapid-app development.
One needn't look far to find arguments that there is still something unique to Lisp that differentiates it even from very recent languages which have had ample opportunity to borrow from Lisp. But one rarely finds a really clear articulation of that uniqueness. Do you think concur with the view that Lisp is still unique, and if so, do you think that Lisp's putative advantage really is ineffable?
If there is an advantage but it's ineffable and therefore opaque to managers with purchasing power, that would explain why Franz, Harlequin, et al have had such a rocky road. Does the Lisp/Scheme community regard this as a worrisome issue? (Some folks on c.l.lisp clearly don't think so, but I don't know if they are just a noisy minority.)
KMP: I guess I think Lisp is unique, but whether it is or not doesn't affect its usefulness as a tool. I'll enumerate some things I like about Lisp, but Slashdot readers shouldn't assume that I'm asserting for each of these features that Lisp has a lock on these. Various other languages surely have some of these. But I am often heard to say: languages are ecologies. Language features are not a priori good or bad. Rather, language features are good or bad in context, based on how well they interact with other language features. Some of what makes Lisp what it is has to do with the features it offers, but some of what makes Lisp what it is has to do with how the features work together to make a coherent whole. Lifting some of these features out of context might sometimes work, but in other cases, it might not. To get a real feel for Lisp, or any language, I think you have to really use it.
Also, in my 1994 article Lambda, the Ultimate Political Party, I advance the hypothesis that languages are defined as much by their community as by their semantics. That is, languages are forever in flux, and the semantics you read about in a language spec is a point in a multi-dimensional space telling you the current location, but it does not tell you the velocity vector in that space. For that, you must look to the community. Even if two languages happened to occupy precisely the same point in design space, that is, if they had the same semantics, would they continue to over time? I think not.
For what it's worth, here are just some of the things I personally like about ANSI Common Lisp:
-
Lisp is dynamic. The world is ever changing and it's useful to allow programs to change dynamically with it. I can load new or changed functions, classes, and method definitions into a running image that I'm debugging, or even in a deployed production application. When I do, the code that was running will immediately start using the new definitions. Classes can be redefined even if the new class has different slots, and, if I care to, I can control how the update is done from old to new slot arrangements for already-created instances. This kind of thing supports programs that must be continually running yet must be responsive to changes or even just bug fixes.
-
Lisp is introspective. Not only can functions, packages, classes, methods be dynamically added, redefined, or removed, but programs can also inquire about whether aspects of the programming environment (functions, packages, classes, and so on) are defined, can manipulate those objects as data, can save them away, can transform or encapsulate them, etc. Also, the Lisp compiler is a standard part of the language and can be invoked even at runtime by applications that need to augment themselves. New programs can be created on the fly, then compiled and loaded and executed in the same running image as they were created, without ever exiting (and even without doing file I/O). This facilitates automatic programming and the development of layered languages.
-
Lisp's syntax is malleable. There's nothing worse than being stuck in a syntax that you don't like in a language you're going to use for a long time. Lisp allows programmers to reconfigure the syntax rules for parsing characters into data and programs, as well as allowing macro technology that transforms one parsed program expression into another. And it allows control of how data is displayed during program execution and debugging. Moreover, this can generally be done in such a way that one programmer's customizations don't adversely impact another's. This makes interactions with Lisp more pleasant and debugging sessions more productive.
-
Lisp doesn't force users to use variable type declarations in order to just get a program to run. The initial focus in Lisp is on getting programs working. You can add type declarations when you're done if you want to, in order to enable additional compiler optimizations. This facilitates rapid prototyping by first getting an application running quickly with low overhead, and then allowing an application to be tuned as a second pass operation.
-
Lisp has a powerful class system, and a flexible meta-class system. The class system allows powerful slot and method definition, method combination, and a great many other detailed features. The meta-class system allows users to treat the object system as data that can be programmed, creating new kinds of classes.
-
Lisp gives the user powerful tools for both signaling and handling errors. This means that when an error occurs, there are often a variety of ways to continue programs other than simply aborting or dumping core. Moreover, object-oriented error handling allows programs to represent errant situations, evaluate the options for how to proceed, and select an appropriate option under program control.
-
Lisp uses automatic memory management. This means that when a programmer is done with an object, they just let go of it and the garbage collector reliably frees its storage. This means Lisp programs do not suffer from the memory leaks that commonly plague programmers in many other languages.
by kfogelFor myself and a number of friends, Lisp/Scheme programming has for too long been a kind of mystical Eden, fading in our memories, from which we have been mostly banished in our professional lives. But we can still recall how it felt to work in a language able to shape itself to any pattern our minds might ask: coding was more interesting and more expressive, and the rate of increasing returns over time was tremendous, because fine-grained -- almost continuous -- abstraction was in the nature of the language. Life was just more fun, frankly.
Alas! In our jobs and even in our personal projects, we are often forced to use C, C++, Java, Perl, or Python -- not because we prefer to write in those languages, but for two much less satisfying reasons: first, everyone else knows those languages, so we'll get more developers with them. And second, you can't count on users and testers having the right environment to run programs written in Lisp/Scheme, so right away you take a portability hit if you choose to develop in them.
Do you think there is a chance of Lisp/Scheme becoming "mainstream" again? That is, when someone contemplates starting a project, it would be as realistic for them to consider Lisp or Scheme as, say, Perl, without worrying about losing developers or initial testers? What will it take?
KMP: First, let me say that I really appreciate the poetic description you offer in the first paragraph above. I very much think that captures how I and others think about the experience of using Lisp.
And as to the future of Lisp, I think the situation for Lisp is looking pretty upbeat these days. Enough so that my own infant business is building its tools in Lisp, both for sale and for our own internal use on products we produce.
There are a lot of implementations, both commercially maintained and "free", with a wide range of delivery options, from conventional executables to "remote" solutions: Some implementations support CORBA and/or COM interfaces, for example. Also, most implement some kind of sockets interface, and there are several Lisp-based web servers available that build on this. Lisp programs can dynamically load DLLs, or can be delivered as DLLs themselves. They can do "foreign function call" to functions in other languages. It can also communicate with databases, and so with other programs via databases.
As the world moves increasingly to high-bandwidth global connectivity, I think the issue of the delivery environment will become less important. People have been waiting for an e-Service based society to take off, and it hasn't quite done that yet, but I think it's coming. I can't see how it won't. The overall savings in quality assurance and support of not having to re-deploy an application in a hostile customer-premise environment will be a lot, just as your question implies. One will just bring an application up on the right kind of hardware, connect it to the net, and then forget about where the program is actually being used. That may be an oversimplification today, but I wouldn't waste my money betting against it for tomorrow.
8) Questions I've Come Across Learning Lisp
by Jon HowardI was recently (April) hired-on as webmaster at Franz [franz.com], a commercial lisp company (we make Allegro Common Lisp [franz.com]) which has introduced me to lisp in a very loud way. Since joining these guys (and gals), I've been thoroughly indoctrinated - with my full consent - because of my belief that as computing hardware progresses programming in more abstract languages will allow for more creative and effective use of the platform. Sure, coding assembler on a new super-duper petaflop chip will still be possible and less wasteful, but who would want to code a million lines of asm to save a few (or even a few thousand) operations out of a few billion, or trillion when it will only net a difference of nanoseconds in the end? I'm less interested in making super-fast programs than I am in making artistic and super-functional programs.
I'm not expressing the views of Franz, every member of the company has their own beliefs on what makes for great programming - which is one of the major reasons I find this place so fulfilling, everyone has complex reasons for their design considerations, and everyone communicates them (something I've grown to appreciate from working in too many places where this was definitely not the case), and consequently I've been exposed to quite a few different techniques of Lisp coding since my introduction half a year ago. I'm constantly amazed that so many different styles of programming can be expressed in the same language, it's capable of accommodating any logical thought process that can be converted to code - and I doubt many of you often use recursion in a logical way on a daily basis, but even that can be done efficiently in lisp.
I'm still very new to lisp, and I was never a serious programmer in the past, but I've always been accustomed to asking questions, and here are a few that I'd like some input on:
- If you learned any other programming language, did you initially find the formalities of its structure to be a significant stumbling block to understanding the language as a whole? Was the same true of learning lisp?
- How much time do you spend debugging non-lisp code? How much on lisp?
- What language took you the most time to learn - was it your first?
- What feature do you consider to be the most important for an abstract language to support efficiently - and which features have you found to be most poorly implemented in lisp distributions?
I'd love to hear about what people think sucks about lisp and needs improvement - or can't be improved, so far I haven't found anything that I could complain about, the most difficult thing for me has been managing all the documentation on a half-century old language in the process of learning it. I've begun to love working in lisp, but I suppose being surrounded by a group so full of passion for it has helped contribute to my bias - if I'm wrong, help snap me out of it with a good argument against using lisp. ;)
KMP: I knew FORTRAN and Basic before I learned Lisp. And I've dealt with numerous languages of all kinds since learning Lisp. With most, the syntax itself is generally not a burden. Some languages have more pleasant syntaxes than others, but the human brain has an amazing ability to cope. Of all the many languages and syntaxes I've seen, about the only thing I've never been able to cope with is the "*" used to notate indirection in C. I understand thoroughly the notion of pointer indirection, and the difference between "pointer to array" and "array of pointers", but I find it forever hard to read and write that particular awful notation for some reason. Give me Teco or Perl any day.
Mostly, though, I think the issue of how hard a syntax makes it to learn a language is overblown. Humans have brains that are adapted to processing myriad special cases and can mostly cope with obscure syntaxes. The real issue is how hard it is for humans to pass on their knowledge to programs. People are good at judgment, and programs are good at repetition. Over time, though, judgment tasks become repetitive and it's time for programs to take them over. I like to write macros to package up things I do a lot, and the key to that is having a reliable mapping between program syntax and program structure. The last thing one wants is a macro language based on character syntax, since such syntax is too unpredictable. Lisp offers macros based on program structure, and that greatly reduces the number of programmer errors one makes in macro writing.
As to debugging, I try to use non-lisp code as little as possible because of how hard it is to debug. Most other languages don't have good visual representations of their data, so when I get in the debugger, the manner in which I am presented with errant data is usually low-level and hard to read. A great deal of my valuable time is spent painstakingly piecing structure back together. But in Lisp data objects have familiar visual representations and I find it's usually easier to see what has gone wrong.
What language took me the most time to learn? Probably Teco. There was a lot of trivia to learn there. What language took the least time? Probably FORTRAN, BASIC, Lisp, HyperTalk, and MOO. Fortran just because it was small. The others because they are highly interactive, which is a huge boon to learning.
Actually, I learned PostScript very fast, too. There are some excellent cookbooks on this. But I never learned to debug PostScript. When my programs erred, I mostly just wrote them anew and hoped they'd work then because debugging was too painful.
What do I consider it most important for an abstract language to support efficiently? My time. Time is the only true, non-renewable commodity. I eschew languages like C because they often waste enormous amounts of my time trying to develop and debug programs, and justify it on the basis of micro-differences in speed that have just never ended up mattering to me. I regard C as appropriate for use as an assembly language, but it doesn't provide enough high-level services for me. When I'm old and grey and look back on my life, I want to have done a lot of interesting things, not just have done a few interesting things but "boy were they fast".
I think it's important to pick a language not on the basis of how fast its implementations are today, but on the basis of how much they do what you want. Lisp has an undeserved reputation for being slow, which I think results from deciding to make it do things that there are not always known optimizations for at the outset. Like garbage collection. But as Lisp is used, people complain about the things that are slow, and fixes get found. So Lisp moves ahead. If Lisp had started instead only with the things it knew how to implement efficiently, it would be holding things back. I want my ideas to lead my technology and my tools, not to have my technology and tools leading my ideas.
9) Basis set for programming languages?
by PseudonymousCowardAs a Scheme and Common Lisp programmer, I got excited when I heard that the Java Virtual Machine would have automatic memory allocation and garbage collection. I thought it would be possible to build Lispish languages to run on the JVM. The rate at which Kawa has been developed, to implement a near-Scheme on the JVM has been frustrating to me. I attribute this at least in part to the absence in the JVM of a construct equivalent to Scheme's continuations. Do you think it is feasible to establish a "basis set" of programming language concepts on which all programming languages could be built, so that the distinctions between C, Scheme, etc would be "merely" syntactic? If yes, please enumerate your candidate set.
KMP: Well, continuations are just functions. What's really lacking to make this easier is good tail call support so that continuations can be called correctly without pushing stack.
I don't really have personal experience with using the JVM directly, but my experience with the MOO programming language led me to believe that there might be a problem with integrating tail calling and security, since sometimes security is implemented by asking "who called me?" and tail calls can mean that the apparent caller is not the real caller. So I asked my spies at Sun about this.
I'm told that the original security model for Java worked the way I expected (by examining the call chain), and that concern over consequent security matters contributed to the absence of tail calling support in early releases. But apparently it was conceded a long time ago that such support should be added some day, and that day simply hasn't come yet. So perhaps there is hope.
Even so, I'm not so sure no matter how hard you try that you can just paper over the many differences between languages and say that the only remaining issues are ones of syntax. I do think you can probably get to a point where all languages can compile to this machine, but that may not always mean that programs in one language are as efficient as those in another, or that data structures in one language are as naturally represented as those in another. For example, both Lisp and Scheme assume that small integers (that would fit in a machine number) are still integers; they don't have the int/Integer disjointness that Java has. A Lisp-to-JVM compiler could presumably hide this distinction, but it would be wrong to say that the only difference between Java and Lisp was syntax--there are really some material philosophical disagreements between the two languages.
10) Scheme as an XML Translation Language
by EvangelionI've become fairly interested lately in using Scheme (probably mzscheme) and the SXML package as a way to do arbitrary XML translations in my free time (if I had any).
From the looks of it, the ability to create a reflexive mapping between an arbitrary XML document and an interpretable programming language is too powerful to be ignored.
Do you think that in the future one of the primary roles of Scheme/Lisp is going to be in manipulation of XML documents, or is this going to be relegated as an academic curiosity while the world struggles through parsing XML in Java?
KMP: Are those my only two choices? The second one sounds awfully bleak. I'd better choose the former.
I don't know whether you'll see XML as a formal part of either Lisp or Scheme any time in the near future, but a lot of that is because the standards bodies administering these are not extraordinarily active at this time. That doesn't mean the languages are dead, just stable. Ongoing work is mostly happening at the level of libraries, and such libraries can generally be written by anyone using existing primitives, without modifications to the core language.
Lisp manipulation of XML and HTML is something people have been working on for a long time. For example, the Document Style Semantics and Specification Language (DSSSL) was a purely functional, side-effect free variant of Scheme. Even XSL, the apparent replacement to DSSSL, offers the same kind of functionality. It just uses a more CSS-like page model and XML syntax. But, conceptually, it's Scheme inside.
In my recent professional life, I have personally written several XML parsers, all in Lisp, for various employers and most recently for myself and my fledgling company. My company's implementation is not available on the market yet, but when it is, I'm quite sure the chief competition will not be around the availability of mere "availability". Already there are a variety of libraries related to XML, XSL, and SAX floating around. And I'm quite sure there will be more to come. Competition will be over things like efficiency, robustness, representation, and optional additional features.
11) Lisp vs. the world
by hjsWhat do you see as the unique strengths and weaknesses of Lisp?
What strengths does it specifically have over other functional languages (such as ML), over structured languages (such as C, Algol, etc), over object oriented languages (such as C++, smalltalk, simula, etc), and over scripting languages (such as TCL, perl, etc)? Can these other languages or classes of languages be enhanced to include these strengths? If so, how, and if not, why?
What about weaknesses? What do you see as the weaknesses of Lisp, both in general and in comparison to the above classes of languages? Can these weaknesses be eliminated? If so, how and if not, why?
I mean strengths and weaknesses not only in the formal sense of the language itself, but also in terms of its usability in today's world. For example, difficulty in delivering binaries or lack of accessibility of system libraries from within common implementations of a language would be considered weaknesses.
KMP: There are so many things I like about Lisp, but most of them come under the heading of "doing things in the right order."
For example, type declarations in many languages are required but in Lisp they're optional. I prefer to first get my program working, and only then to tune it to be more efficient by adding type declarations. What's the point of doing a lot of make-work declarations if you're not even sure you're going to keep the result? I do a lot of exploratory programming just to answer "what if" questions. I also write lots of little throwaway programs just to compute a simple result. I don't need such programs to run in 5 microseconds instead of 10.
I also view the process of programming as a series of "times" at which decisions can be made: "coding time," "parsing time" (Lisp calls this "read time"), "macro expansion time," "compilation time," "load time," and "execution time." Lisp gives me a great deal more control for each piece of code as to when it runs, so that it can run at the appropriate time when the data it depends on is known. Other languages, especially statically typed ones, often make me specify information too soon, before it is really known, which usually means "making up" answers instead of really knowing the answers. Sometimes that makes programs run faster. Sometimes it just makes them run wrong.
And I like Lisp's willingness to represent itself. People often explain this as its ability to represent itself, but I think that's wrong. Most languages are capable of representing themselves, but they simply don't have the will to. Lisp programs are represented by lists and programmers are aware of that. It wouldn't matter if it had been arrays. It does matter that it's program structure that is represented, and not character syntax, but beyond that the choice is pretty arbitrary. It's not important that the representation be the Right® choice. It's just important that it be a common, agreed-upon choice so that there can be a rich community of program-manipulating programs that "do trade" in this common representation.
I write a lot of macros because there are a lot of interesting things one can do with macros in Lisp. In other languages, macro-writing is a process of manipulating strings containing input syntax. That feels very unreliable and I've never liked that. Lisp's willingness to represent its code in known data structures makes macro writing feel a lot more reliable. And the presence of macros in Lisp generally means that the boring parts of coding get removed, because repetitive patterns usually get captured by a macro and hidden away, keeping the developer's attention on the "interesting parts", and making the activity of programming itself both more fun and more efficient.
Could other languages borrow some of Lisp's strengths? Sure. And they do. Java, Dylan, and I suspect even C++ have all borrowed ideas from Lisp. But that's ok. We'll make more. And anyway, it's not a zero sum game. Everyone benefits when there's this kind of cross-pollination, whether it's Lisp influencing other languages or vice versa.
Weaknesses of the language? Well, that's harder to say. I think the basic design is quite strong. Sometimes you see an implementation that has put more energy into some parts of the language than others, but usually that has created a market opportunity for another, so overall we have our bases covered.
For example, you might find some implementations that have big "hello world" footprint sizes compared to "hello world" in other languages. Some in the Lisp community, don't think this matters much, because disk and RAM are getting ever cheaper. "Real" applications (i.e., not "hello world," but something meaty) of 5-10 megabytes are pretty commonplace these days. Years ago, Lisp used to be seen as large, but due to such criticism, Lisp has held its size constant in the last decade while other languages and systems have bloated rapidly. So nowadays, Lisp is comparatively quite small. And even still, if you don't like the size you get from one vendor, it seems there's always another trying to squeeze into the niche of addressing your need. Corman Common Lisp (an up-and-coming commercial implementation) and CLISP (a GPL-style "free" implementation) have given special attention to this issue. So there's a vendor for everyone on the size issue. And, though I deal more often in Common Lisp in my day-to-day work these days, I would be remiss if I didn't mention that image size is also a key concern of the Scheme language community, so that's yet another way the size issue is addressed for those who see it as critical.
Some might have heard that Lisp, being dynamic, doesn't make use of static type information. This isn't quite right. In fact, the language doesn't require static type analysis, it merely permits it. This gives a lot of leeway to each implementation to address the specific needs of its own customer base. The CMU Common Lisp implementation has, for example, addressed the issue of type analysis in great detail and offered a clear demonstration that there are many exciting things that implementations of Common Lisp can do with type declarations if they choose to.
Why don't all implementations optimize all of these aspects--footprint size, static type analysis, etc.? The Common Lisp language is admittedly conceptually large and correct, efficient compilation requires considerable time and cleverness to implement. "Why not make the language smaller so it requires less work to implement?" is a query you hear a lot from the outside, and even from members of the Scheme community. The answer from the Common Lisp community amounts to this: Programs are written all the time, but implementations are written much more rarely. What the implementation does not do is left for the user. The more hard work the language does, the less hard work programs do. In effect, the thesis of Common Lisp is that bigger languages make for smaller sentences in the language. (To see that there is at least some intuitive basis for this, think about how long a novel like Gone With the Wind is in English, then try to imagine whether the same novel re-expressed in Esperanto would be longer or shorter.)
If a language offers only what a programmer could implement overnight, it gives its programmers not much of a leg up on their final application. Many members of the Scheme community boast that they have written a Scheme implementation, while many Common Lisp programmers have not. Common Lisp is surely harder to implement, but the Common Lisp community does not see as its primary purpose to put out legions of implementors, each with their own easily-created implementation. The Common Lisp community has chosen to be about commercial applications, and its designers have provided a "meaty chunk" of useful power for programmers to use, with the promise that if programmers write their programs to that standard, not only will those programs work well today, but as implementations get better, those same programs will work even better tomorrow.
[to be continued...] -