Concepts that surprised you when you read SICP? - sicp

SICP - "Structure and Interpretation of Computer Programs"
Explanation for the same would be nice
Can some one explain about Metalinguistic Abstraction

SICP really drove home the point that it is possible to look at code and data as the same thing.
I understood this before when thinking about universal Turing machines (the input to a UTM is just a representation of a program) or the von Neumann architecture (where a single storage structure holds both code and data), but SICP made the idea much more clear. Scheme (Lisp) helped here, as the syntax for a program is exactly the same as the syntax for lists in general, namely S-expressions.
Once you have the "equivalence" of code and data, suddenly a lot of things become easy. For example, you can write programs that have different evaluation methods (lazy, nondeterministic, etc). Previously, I might have thought that this would require an extension to the programming language; in reality, I can just add it on to the language myself, thus allowing the core language to be minimal. As another example, you can similarly implement an object-oriented framework; again, this is something I might have naively thought would require modifying the language.
Incidentally, one thing I wish SICP had mentioned more: types. Type checking at compilation time is an amazing thing. The SICP implementation of object-oriented programming did not have this benefit.

I didn't read that book yet, I have only looked at the video courses, but it taught me a lot. Functions as first class citizens was mind blowing for me. Executing a "variable" was something very new to me. After watching those videos the way I now see JavaScript and programming in general has greatly changed.
Oh, I think I've lied, the thing that really struck me was that + was a function.

I think the most surprising thing about SICP is to see how few primitives are actually required to make a Turing complete language--almost anything can be built from almost nothing.
Since we are discussing SICP, I'll put in my standard plug for the video lectures at http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/, which are the best Introduction to Computer Science you could hope to get in 20 hours.

The one that I thought was really cool was streams with delayed evaluation. The one about generating primes was something I thought was really neat. Like a "PEZ" dispenser that magically dispenses the next prime in the sequence.

One example of "the data and the code are the same thing" from A. Rex's answer got me in a very deep way.
When I was taught Lisp back in Russia, our teachers told us that the language was about lists: car, cdr, cons. What really amazed me was the fact that you don't need those functions at all - you can write your own, given closures. So, Lisp is not about lists after all! That was a big surprise.

A concept I was completely unfamiliar with was the idea of coroutines, i.e. having two functions doing complementary work and having the program flow control alternate between them.

I was still in high school when I read SICP, and I had focused on the first and second chapters. For me at the time, I liked that you could express all those mathematical ideas in code, and have the computer do most of the dirty work.
When I was tutoring SICP, I got impressed by different aspects. For one, the conundrum that data and code are really the same thing, because code is executable data. The chapter on metalinguistic abstractions is mind-boggling to many and has many take-home messages. The first is that all the rules are arbitrary. This bothers some students, specially those who are physicists at heart. I think the beauty is not in the rules themselves, but in studying the consequence of the rules. A one-line change in code can mean the difference between lexical scoping and dynamic scoping.
Today, though SICP is still fun and insightful to many, I do understand that it's becoming dated. For one, it doesn't teach debugging skills and tools (I include type systems in there), which is essential for working in today's gigantic systems.

I was most surprised of how easy it is to implement languages. That one could write interpreter for Scheme onto a blackboard.

I felt Recursion in different sense after reading some of the chapters of SICP

I am right now on Section "Sequences as Conventional Interfaces" and have found the concept of procedures as first class citizens quite fascinating. Also, the application of recursion is something I have never seen in any language.

Closures.
Coming from a primarily imperative background (Java, C#, etc. -- I only read SICP a year or so ago for the first time, and am re-reading it now), thinking in functional terms was a big revelation for me; it totally changed the way I think about my work today.

I read most part of the book (without exercise). What I have learned is how to abstract the real world at a specific level, and how to implement a language.
Each chapter has ideas surprise me:
The first two chapters show me two ways of abstracting the real world: abstraction with the procedure, and abstraction with data.
Chapter 3 introduces time in the real world. That results in states. We try assignment, which raises problems. Then we try streams.
Chapter 4 is about metalinguistic abstraction, in other words, we implement a new language by constructing an evaluator, which determines the meaning of expressions.
Since the evaluator in Chapter 4 is itself a Lisp program, it inherits the control structure of the underlying Lisp system. So in Chapter 5, we dive into the step-by-step operation of a real computer with the help of an abstract model, register machine.
Thanks.

Related

functional programming and self-commenting code - is this really possible?

As I got a lot of spare time to spend ATM I read a few threads/comments on code-comments and documentation here.
As most people here I too think that you should write your code so that it's easy to read and self-commenting as far as it's possible.
On the other hand I am a huge FP-fanboy - and yes if you write your code the right way it will be very readable in FP - or so I thought.
Problem is that tiny things make a awful lot of difference in FP-world. If your colleague doesn't fully understand FP he might be able to "read" the indentation of the code but won't be able to modify or fully understand it. That stands for languagues like Haskell, where a '.' or '$' makes a big difference and also for languages like F# or even C# of VB.NET with lots of LINQ statements.
At first glance the problem might be, that your peer just doesn't get the language and it's not the codes fault - on the other hand: who truly gets all of FP? Look at some papers concerning Haskell - the code is beautifully crafted and self-commenting but just as in math you may have to chew on a line for several minutes before you get it.
Of course in those papers there will be a text-block trying to clarify just after the code ....
So IMHO you have to comment your FP-code as long as you work in a shop where not every colleague has a PhD in CS ;)
What do you think?
PS: first post here - really looked for answers concerning this questions but didn't find any - please be gentle if I just didn't look hard enough :)
Functional languages greatly favor the development of self-documenting code, because you can freely rearrange the order of functions, and easily abstract out any given part of the code, assigning it an explanatory name.
Abstract, abstract, abstract, is the keyword to master code complexity, and that's where the functional style shines. But there will be always things that cannot be expressed within the code itself.
One clear example is code for algorithms. It is unlikely that one can easily understand a complex algorithm just by looking at the implementation. Yes, functional languages make understanding simpler, becasue many gory details (trivial example: memory management) do not have to be coded explicitly, thus exposing the underlying logic more clearly.
However this is no substitute for an explanation in natural language, which conveys in an intuitive way how it works (and sometimes a picture is worth a thousand words). This is becasue our brain needs to observe difficult concepts from different point of views in order to understand them fully.
What to comment also depends on your audience. Beginners, average programmers or wizards? There is no one-fits-all solution.
E.g. you should explain the meaning of a "." (function composition) in Haskell if you are writing tutorial code, but certainly that would be a redundant explanation for anyone who has gone past chapter one/two of any Haskell book.
On the other hand some specific algorithm, like say red-black trees, could be a given for some programmers, and something very mysterious for others. In the second case you should add many comments to the code, or point to a document with further explanations.
Finally, one should notice that there is no consensus even among the masters. E.g. Dennis Ritchie is famous for being extremely parsimonious with comments, instead Don Knuth is an advocate of "Literate programming", where comments are as important as code itself. A set of rules will never be a substitute for personal taste.

How does functional programming apply to simulations?

Besides the general question in the title,
How do functional programmers and functional languages approach the domain of simulations, which seem to be most naturally handled by object-oriented languages?
Are there open-source examples of complex simulations written in a (mostly) functional style?
What changes of perspective would an OO-programmer need, in order to approach simulations from a functional paradigm?
I'm asking this while learning how Clojure's creator Rich Hickey specifically sought to tame the "incidental complexity" of OO-programming and mutable state, e.g. Clojure's separation of identity and state makes a lot of sense (Hickey's ants.clj is on the study list). Another related area is using functional programming for games, which are often simulations with lots of stateful "things" all over the place; there are some articles/papers written about FP and games, more would be welcome.
Perhaps experienced functional programmers can provide additional background and advice on how to re-orient one's thinking to functional style, specifically for simulations. Thanks in advance!
Michal's answer is excellent, but I thought I'd add a couple other neat examples I've personally found helpful/interesting.
The first is a post (and code) about functional fluid dynamics by Lau Jenson. Though he definitely goes the mutable route for speed here, the style is rather functional. I'd bet by Clojure 1.3 this could be done (mostly!) immutably with reasonable performance.
The next is a simple Snake game implemented in Clojure. Easy enough to read though in an hour or so, and the style is really pleasant and cohesive.
Also, some neat code to look at (I think!) is code modeling neural networks. Jeff Foster has some single layer perceptron code, and some more idiomatic revisions of the code. Worth looking at, even if you're not acquainted with NNs. He also has some more recent posts regarding fluid dynamics, though this time in Haskell. (Part I and Part II) Also fun, I think, is his implementation of the Game of Life (& Part II).
Finally, as Michal mentioned before me, Brian Carper is working on a RPG in Clojure. he recently posted some artwork for the game, so I'm betting it's still being worked on ;)
I love using the sequence libraries for working with tons of data; it feels more natural using abstractions like map and reduce, and fun, handy tools like juxt rather than simple imperative iterations. You do pay a tax, I've found, by using Clojure/functional langs in reimplementing well-known and well-implemented imperative algorithms.
Have fun!
I'm not sure that I'm up to the challenge of writing up a comprehensive analysis of the problem posed in the question, but I can at least post some links interesting on the FP vs. games front:
Jörg W. Mittag provides a number of interesting examples in this answer to a question on "real world" Haskell programming (with links to some interesting write-ups -- the Purely Functional Retrogames series is really worth a read).
In Clojure land, Phil Hagelberg has implemented a text-based adventure game for his PeepCode screencast on Clojure programming; the code is available on GitHub. Then there's Brian Carper's RPG project; no code publicly released yet and just that one post from a while ago (it looked very cool, though, so let's all come together to pressure Brian to continue ;-)). Finally, here's an example of a simple game using Penumbra (for some reason -- possibly unrelated to Clojure -- I couldn't get it to work, but may you will, plus there's a write-up attached).
As for simulations, studying ants.clj is a great idea. Also, I remember seeing a series of SICP-based lectures from an introductory programming course at UC Berkeley (I think...?) available somewhere (90% it was on their YouTube channel); they've got three lectures on OOP in Scheme and I think they mention simulation as a domain providing good use cases for the approach. Note that I have a pretty vague memory of this one, so it's hard for me to say how useful it might be to you.
I'm writing a game in Clojure, using a mostly functional style. For example, the entire game state is modelled as an immutable data structure.
This has required some slightly convoluted coding. For example, you frequently end up creating functions with a lot of parameters to pass around various elements of game state and ensure that application of game state updates happens to the very latest game version.
But it has also thrown up some really nice advantages, for example concurrency has proved pretty trivial and you can do fun things like cloning the entire game state to run different simulations in the AI.
Overall, I'm delighted with Clojure as a language for simulations / games.
Based on this experience, the things I think would improve Clojure for games / simulations would be:
Better support for primitives, especially as function parameters and return values
Implementation of core language functions that are less hard on memory allocations (GC pressure is an issue for interactive games!)
You can see an early version of the game here: Ironclad - Generals of Steam. It's basically a steampunk themed strategy game.
Uncle Bob has been playing with Clojure lately and in particular writing an orbital simulator as his most public example.
Some links:
Blog post
Code on github
To complement the other answers: There is a discipline called Functional Reactive Programming that addresses the issue of functional representation of systems that change in time and react to outer events. See
What is (functional) reactive programming?
Is functional GUI programming possible?
Functional Reactive Programming at The Haskell Wiki.
Simulations are a form of interpreter -- which are easy to write in a functional style. They can be also designed as self-optimizing simulators, based on treating them as a compiler.

should we teach pointers in a "fundamentals of programming" course?

I will be teaching a course on the fundamentals of programming next Fall, first year computer science course. What are the pros and cons of teaching pointers in such a course? (My position: they should be taught).
Edit: My problem with the "cater your audience" argument is that in the first couple of years in University, we (profs) do not know if students would like to be scientists or not... we wish we knew, but we have to strike a balance between those who will remain in school (4 years does not a scientist make), and those who will be engineers.
Final decision: At least references, but possibly pointers without pointer arithmetic.
At the very least you should teach references or some equivalent concept. I think you should probably take it easy on things like pointer arithmetic, c arrays and strings, but indirection is a very important concept in computer science, and students should be introduced to it.
Yes.
Pointers underpin a huge number of concepts in other, higher level languages, and I'm firmly of the opinion that you need to teach a certain amount of the lower-level stuff to facilitate a good understanding of why we bother with anything higher level at all.
Once you understand a bit about how memory is allocated, and how it's addressed and manipulated with pointers, explaining a lot of other constructs gets easier. For example, explaining a NullPointerException in Java, or even the concept of references in such languages is child's play if you've got someone who understands pointers in C (and better still, if they also grok references in C++).
Absolutely teach them. Understanding indirection is essential for programming, whether it's with pointers, references, dynamic binding, or any number of other things. Now obviously don't start off with them, but understanding indirection is at least as important as understanding control flow ideas.
The con of course is that some people just won't get it and will do poorly or drop out. If this is a course for people who want to be CS majors then don't sweat it because you're just giving them incentive to switch majors earlier rather than later. If it's more or a general ed course for people who are kind of interested in programming, then they should probably still be introduced, but not graded harshly or heavily.
During my first year as a CS student, I took a Java course in fall which was the general intro. The professor didn't teach pointers directly, but he did teach the concept of references, and why you can modify objects and not when primitives when either is passed in an argument.
During my 2nd semester, I took the next course in the series, which was about C, and this class heavily relied on pointers.
For an intro to programming class, I'd say just mention references, but not pointers directly.
I think that a "fundamentals of programming" course should at least touch on basic processor architecture and assembly language, and if it does, you can't really make a case for not discussing pointers.
If you only teach higher-level (byte-code) languages, then I guess pointers would confuse the audience.
Pros: solid understanding of the way that memory is used by the machine, the difference between (and pitfalls of) pointers to data on the heap vs. pointers to data on the stack, passing methods by address, etc.
Cons: complex for an audience who is not yet knowledgeable (or has not had enough time to assimilate the concepts) of computer architecture, including what is stack, what are registers, calling conventions, etc.
So, to summarize, it depends a lot on your audience and on the language(s) you'll tackle (pointers will be meaningless in the context of LISP or Java), as well as on how deep you are willing to go in the direction of what is heap, what is stack, how scope is translated into stack (i.e. why never to return a pointer to a local variable), etc.
When I taught pointers to an engineering class I ultimately fired up a debugger on a simple "hello world" program, and showed the students the actual machine code, register values and corresponding memory dumps, with the stack manipulation and parameter passing, etc., but they were ready for it. Would your audience be receptive to such a drill-down expedition, to ensure solid understanding of what's going on behind the scenes, and would you be willing to go to such lengths? :)
I think you shouldn't teach it first. But later, once basic concepts of programming are acquired.
A good example is the last Stroustrup book : Programming -- Principles and Practice Using C++ where he teach how to make a parser, I/O (streams) usage and GUI usage before even talking about pointers!
I think it will be a good reference for teaching because it is more natural to understand the way we build ideas instead of how much constraints (memory management for example) we have to handle at the same time to make a software work. I really recommand you this book to have a fresh perspective about teaching fundamentals of programming.
It really depends on the goal of your course - teaching programming and teaching computer science are two separate goals, and though they are not mutually exclusive, introductory classes generally do not teach both equally well. Here's an example of the difference: say we want to learn how to sort a list. A programming course in C++ would teach you to use the syntax of a std::sort function template, and homework might be writing several comparison functors. A computer science course would explain to you what a merge sort is, what the algorithm looks like in pseudo-code, and its performance/space characteristics, and homework would be writing the sort function itself.
So if you are teaching introductory programming, then yes, you should teach your students about pointers.
If you are teaching computer science, then no, there is no need to understand pointers at an introductory level.
Anybody who calls themselves a good programmer must know how pointers work; being a good programmer implies that they do not know only a single programming language, but that they know how programming languages work in general, allowing them to adapt to programming languages they haven't seen before.
This doesn't mean that a fundamentals of programming course should be teaching pointers, however.
If your goal is to give these people a complete, well rounded familiarity with programming languages in general, then yes pointers shall be part of that.
If your way of introducing them to programming is to use one programming language at first, with the intention of covering other languages in subsequent courses, and pointers are not relevant to that language, then there's no need to talk about pointers yet.
I think there's a lot to be said by starting people out in one language only, rather than trying to cover every style of language at once.
My first introductory programming course used Haskell. It wasn't until a subsequent course using C that pointers were introduced (I was already a good C and C++ programmer when I took the course; those subjects were mandatory).

How do I get my brain moving in "lisp mode?"

My professor told us that we could choose a programming language for our next programming assignment. I've been meaning to try out a functional language, so I figured I'd try out clojure. The problem is that I understand the syntax and understand the basic concepts, but I'm having problems getting everything to "click" in my head. Does anyone have any advice? Or am I maybe picking the wrong language to start functional programming with?
It's a little like riding a bike, it just takes practice. Try solving some problems with it, maybe ProjectEuler and eventually it'll click.
Someone mentioned the book "The Little Schemer" and this is a pretty good read. Although it targets Scheme the actual problems will be worth working through.
Good luck!
Well, for me, I encountered the same problem as you do in the beginning when I started doing OCAML, but the trick is that you must start thinking about what you want from the code and not how to do it!!!
For example, to calculate the square of list's elements, forget about the length of the list and such tricks, just think mathematically like that:
if the list is empty -> I am done
if not, then the list must have a head and tail -> you calculate the square of the head, then ask your function to do the same with the tail.
Just think about the general case and the base one, and that you are emitting data and not modifying it (unless you want to modify it ;) ).
Good luck!
You could check out The Little Schemer.
How about this: http://www.defmacro.org/ramblings/lisp.html
It is a very simple, step-by-step introduction to thinking in lisp from the point of view of a regular imperative programmer (Java, C#, etc.).
For educational purposes I would recommend PLT Scheme. It is a portable and powerful environment with very good examples and an even better documentation. It will help you to discover the thoughts behind functional programming step by step and in a very clean way. Choosing a little application to implement will help you learning the new language.
http://www.plt-scheme.org/
Additionally "Structure and Interpretation of Computer Programs" of H. Abelssn, G. Sussman, and J. Sussman is a very good book regarding Scheme (and programming).
Regards
mue
Take a look at 99 Lispy problems
Some thoughts on Lisps, not specific to Clojure (I'm not a Lisp expert, so I hope they're mostly correct and useful):
Coding in AST
I know little about compiler or interpreter theory, but every time I code in Lisp, it amazes me that it feels like directly building an AST.
That's part of what "code = data" means, coding in Lisp is a lot like filling data structures (nested lists) with AST nodes. Amazing, and it's easy to read too (with the right text editor).
A Programmable Programming Language
So code chunks are just nested lists, and list operations are part of the language. So you can very easily write Lisp code that generates Lisp code (see Lisp macros). This makes Lisp a programmable (in itself!) programming language.
This makes building a DSL or an interpreter in Lisp is very easy (see also meta-circular evaluation).
Never reboot anything
And in most Lisp systems, code (including documentation) can be introspected and hot swapped at run time.
Advanced OOP
Then, most Lisp Systems have some sort of Object System derived from CLOS, which is an advanced (compared to many OOP implementations) and configurable Object System (see The Art of the Metaobject Protocol).
All these features where invented long ago, but I'm not sure they are available in many other programming languages (although most are catching up, e.g. with closures), so you have to "rediscover" and get used to these by practicing (see the books in other answers).
Just remember: it's all data!
Write some simple classic functions that Lisp is good at, like
reverse a list
tell if an atom is somewhere in an s-expression
write EQUAL to tell if 2 s-expressions are equal
write FRINGE to get the list of atoms at the fringe of an s-expression
write SUBST, then write SUBLIS
Symbolic differentiation
Algebraic simplification
write a simple EVAL and/or APPLY
Understand that Lisp is good for these kinds of no-side-effect functional programs.
It is also useful for stateful side-effect (non-functional) programs, but those are more like "programs" than "functions".
Which is better for a given application depends on the application. In general, it should contain no less, and no more, state information than necessary.
Easy!
M-x lisp-mode
OK, OK, so you might not have Emacs for a brain. In all seriousness, what you need to do is to get really good at recursion. This can be quite a brain warp initially when trying to extend the concept of recursion beyond the canonical examples, but ultimately it will result in more fluid, lispy code.
Also, a lot of people get hung up on the parenthesis, and I don't really know why - the syntax is very simple and consistent and can be mastered in minutes. For me, I came to Scheme after having learned C++ and Java, and I always thought that the difference between "functions" and "operators" was a false dichotomy, and it was refreshing to see that distinction eliminated.
As far as functional programming goes, as long as you can wrap your head around the fact that a function is a first-class value and can be passed both into and out of other functions you should be fine. The usefulness of this will become clear over time, but it's enough that you can write function-taking and function-returning functions.
Finally, I'm not sure what support Clojure has for macros, but they're considered an essential part of lisp. However, I wouldn't worry about learning them until you're deeply familiar with the above items - though macros are incredibly useful and versatile, they're also used less often than the other techniques I mentioned.
I'd start with a language that can be interpreted. I found Moscow ML to be fairly easy. It is a lightweight implementation of Standard ML.
My personal practice is to find a small project (something that might take 3-5 nights hacking away) and implement it. How about a blog filter tool? Maybe just a Towers of Hanoi or Linked List implementation (those are usually 1-night projects).
The way it usually works out is I implement it poorly the first time, throw away what I had, and it finally clicks a few hours in.
A HUGE help is taking a course in something like... um... LISP! :) The homework will force you to confront a lot of the concepts and it clicked for me long before the semester ended.
Good luck!!
Good luck. It took me until about halfway through the "Programming Languages" course in college before Scheme "clicked". Once that happened, though, everything just made sense, and I fell in love with functional programming.
Write a Lisp interpreter in Lisp.
If you haven't alrady, read up on what makes lisp a unique language. If you don't do this first, you'll be trying to do the same things you could do in some other programming languages.
Then try to implement some small thing (try to make it useful to you or you might not have the motivation).
Lisp in a box is a great way to get your feet wet.
For me the important thing is to make sure you do everything in a 'lisp-y' way. Don't be tempted to think 'In Java I'd use a for loop here, how do I do for loops in Lisp?' but to go through enough examples and tutorials (as someone pointed out, SICP is perfect for this) that you can start to spot when code looks 'Lisp-y' and recognise common language paradigms.
I certainly know the feeling of looking at some code I've just written and intuitively knowing that it's correctly idiomatic for that language and platform/framework - that, I think, is when it 'clicks'.
Edit: And kudos for choosing a functional language, lesser students would have just done it in Java :)
Who said it is going to click? I'm always confused
But if you think about how much abstraction it is possible to hide away, behind lisp macros. Then your brain will explode.
:)
I'd check out Programming Clojure. It's a great book for non-lispers.
In addition to what other SO'ers have already suggested, here are my 2 cents:
Start learning the language and try out a few simple numerical/hobby problems in the language
IMPORTANT: Post the solution/code to StackOverflow, asking for people's opinion if that is really the LISPy way to do it.
Best of luck!

Why should I learn Lisp? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I really feel that I should learn Lisp and there are plenty of good resources out there to help me do it.
I'm not put off by the complicated syntax, but where in "traditional commercial programming" would I find places it would make sense to use it instead of a procedural language.
Is there a commercial killer-app out there that's been written in Lisp ?
Lisp is a large and complex language with a large and complex runtime to support it. For that reason, Lisp is best suited to large and complicated problems.
Now, a complex problem isn't the same as a complicated one. A complex problem is one with a lot of small details, but which isn't hard. Writing an airline booking system is a complex business, but with enough money and programmers it isn't hard. Get the difference?
A complicated problem is one which is convoluted, one where traditional divide and conquer doesn't work. Controlling a robot, or working with data that isn't tabular (languages, for example), or highly dynamic situations.
Lisp is really well suited to problems where the solution must be expandable; the classic example is the emacs text editor. It is fully programmable, and thus a programming environment in it's own right.
In his famous book PAIP, Norvig says that Lisp is ideal for exploratory programming. That is, programming a solution to a problem that isn't fully understood (as opposed to an on-line booking system). In other words: Complicated problems.
Furthermore, learning Lisp will remind you of something fundamental that has been forgotten: The difference between Von Neumann and Turing. As we know, Turing's model of computation is an interesting theoretical model, but useless as a model for designing computers. Von Neumann, on the other hand, designed a model of how computers and computation were to execute: The Von Neumann model.
Central to the Von Neumann model is that you have but one memory, and store both your code and your data there. Notice carefully that a Java program (or C#, or whatever you like) is a manifestation of the Turing model. You set your program in concrete, once and for all. Then you hope you can deal with all data that gets thrown on it.
Lisp maintains the Von Neuman model; there is no sharp, pre-determined border between code and data. Programming in Lisp opens your mind to the power of the Von Neumann model. Programming in Lisp makes you see old concepts in a new light.
Finally, being interactive, you'll learn to interact with your programs as you develop them (as opposed to compile and run). This also change the way you program, and the way you view programming.
With this intro I can finally offer a reply to your question: Will you find places where it outshines "traditional" languages?
If you are an advanced programmer, you need advanced tools. And there is no tool more advanced than Lisp.
Or, in other words: The answer is yes if your problems are hard. No otherwise.
One of the main uses for Lisp is in Artificial Intelligence. A friend of mine at college took a graduate AI course and for his main project he wrote a "Lights Out" solver in Lisp. Multiple versions of his program utilized slightly different AI routines and testing on 40 or so computers yielded some pretty neat results (I wish it was online somewhere for me to link to, but I don't think it is).
Two semesters ago I used Scheme (a language based on Lisp) to write an interactive program that simulated Abbott and Costello's "Who's on First" routine. Input from the user was matched against some pretty complicated data structures (resembling maps in other languages, but much more flexible) to choose what an appropriate response would be. I also wrote a routine to solve a 3x3 slide puzzle (an algorithm which could easily be extended to larger slide puzzles).
In summary, learning Lisp (or Scheme) may not yield many practical applications beyond AI but it is an extremely valuable learning experience, as many others have stated. Programming in a functional language like Lisp will also help you think recursively (if you've had trouble with recursion in other languages, this could be a great help).
In response to #lassevk:
complicated syntax??
The syntax for lisp is incredibly simple.
Killer app written in lisp: emacs. Lisp will allow you to extend emacs at will to do almost anything you can think of that an editor might do.
But, you should only learn lisp if you want to, and you may never get to use at work ever, but it is still awesome.
Also, I want to add: even if you find places where lisp will make sense, you will probably not convince anyone else that it should be used over java, c++, c#, python, ruby, etc.
I can't answer from first-hand experience but you should read what Paul Graham wrote on Lisp. As for the "killer-app" part, read Beating the averages.
I programmed in Lisp professionally for about a year, and it is definitely worth learning. You will have unparalleled opportunity to remove redundancy from your code, by being able to replace all boilerplate code with functions where possible, and macros where not. You will also be able to access unparalleled flexibility at runtime, translating freely between code and data. Thus, situations where user actions can trigger the need to build complex structures dynamically is where Lisp truly shines. Popular airline flight schedulers are written in Lisp, and there is also a lot of CAD/CAM in Lisp.
Lisp is very useful for creating little DSLs. I've got a copy of Lisp in a Box running at work and I've written little DSLs to interrogate SQL server databases and generate data layers etc in C#. All my boiler plate code is now written in lisp macros that output to C#. I generate HTML, XML, all sorts of things with it. While I wish I could use Lisp for everyday coding, Lisp can bring practical benefits.
If you like programming you should learn Lisp for the pure joy of it. XKCD perfectly expresses the intellectual enlightenment that ensues. Learning Lisp is for the programmer what meditation is for the Buddhist monk (and I meant this without any blasphemous connotation).
Any language looks a lot harder when one doesn't use the common indentation conventions of a language. When one follows them of Lisp, one sees how it expresses a syntax-tree structure quite readily (note, this isn't quite right because the preview lies a little; the r's should align with the fns in the recursive quicksort argument):
(defun quicksort (lis)
(if (null lis)
nil
(let* ((x (car lis))
(r (cdr lis))
(fn (lambda (a)
(< a x))))
(append (quicksort (remove-if-not fn
r))
(list x)
(quicksort (remove-if fn
r))))))
I found that learning a new language, always influences your programming style in languages you already know. For me it always made me think in different ways to solve a problem in my primary language, which is Java. I think in general, it just widens your horizon in term of programming.
I took a "lisp class" in college back in the eighties. Despite grokking all the concepts presented in the class, I was left without any appreciation for what makes lisp great. I'm afraid that a lot of people look at lisp as just another programming language, which is what that course in college did for me so many years ago. If you see someone complaining about lisp syntax (or lack thereof), there's a good chance that they're one of those people who has failed to grasp lisp's greatness. I was one of those people for a very long time.
It wasn't until two decades later, when I rekindled my interest in lisp, that I began to "get" what makes lisp interesting--for me anyway. If you manage to learn lisp without having your mind blown by closures and lisp macros, you've probably missed the point.
Learning LISP/Scheme may not give you any increased application space, but it will help you get a better sense of functional programming, its rules, and its exceptions.
It's worth the time investment just to learn the difference in the beauty of six nested pure functions, and the nightmare of six nested functions with side effects.
From http://www.gigamonkeys.com/book/introduction-why-lisp.html
One of the most commonly repeated
myths about Lisp is that it's "dead."
While it's true that Common Lisp isn't
as widely used as, say, Visual Basic
or Java, it seems strange to describe
a language that continues to be used
for new development and that continues
to attract new users as "dead." Some
recent Lisp success stories include
Paul Graham's Viaweb, which became
Yahoo Store when Yahoo bought his
company; ITA Software's airfare
pricing and shopping system, QPX, used
by the online ticket seller Orbitz and
others; Naughty Dog's game for the
PlayStation 2, Jak and Daxter, which
is largely written in a
domain-specific Lisp dialect Naughty
Dog invented called GOAL, whose
compiler is itself written in Common
Lisp; and the Roomba, the autonomous
robotic vacuum cleaner, whose software
is written in L, a downwardly
compatible subset of Common Lisp.
Perhaps even more telling is the
growth of the Common-Lisp.net Web
site, which hosts open-source Common
Lisp projects, and the number of local
Lisp user groups that have sprung up
in the past couple of years.
If you have to ask yourself if you should learn lisp, you probably don't need to.
Learning lisp will put Javascript in a completely different light! Lisp really forces you to grasp both recursion and the whole "functions as first class objects"-paradigm. See Crockfords excellent article on Scheme vs Javascript. Javascript is perhaps the most important language around today, so understanding it better is immensely useful!
"Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot."
--Eric S. Raymond, "How to Become a Hacker"
http://www.paulgraham.com/avg.html
I agree that Lisp is one of those languages that you may never use in a commercial setting. But even if you don't get to, learning it will definitely expand your understanding of programming as a whole. For example, I learned Prolog in college and while I never used it after, I gave me a greater understanding of many programming concepts and (at times) a greater appreciation for the languages I do use.
But if you are going to learn it...by all means, read On Lisp
Complicated syntax? The beauty of lisp is that it has a ridiculously simple syntax. It's just a list, where each element of the list can be either another list or an elementary data type.
It's worth learning because of the way it enhances your coding ability to think about and use functions as just another data type. This will improve upon the way you code in an imperative and/or object-oriented language because it will allow you to be more mentally flexible with how your code is structured.
Gimp's Script-Fu is lipsish. That's a photoshop-killer app.
Okay, I might be weird but I really don't like Paul Graham's essays that much & on Lisp is a really rough going book if you don't have some grasp of Common Lisp already. Instead, I'd say go for Siebel's Practical Common Lisp. As for "killer-apps", Common Lisp seems to find its place in niche shops, like ITA, so while there isn't an app synonymous with CL the way Rails is for Ruby there are places in industry that use it if you do a little digging.
To add to the other answers:
Because the SICP course (the videos are available here) is awesome: teaches you Lisp and a lot more!
Killer app? Franz Inc. has a long list of success stories, but this list only includes users of AllegroCL... There are probably others. My favourite is the story about Naughty Dog, since I was a big fan of the Crash Bandicoot games.
For learning Common Lisp, I'd recommend Practical Common Lisp. It has a hands-on approach that at least for me made it easier than other books I've looked at.
You could use Clojure today to write tests and scripts on top of the Java VM. While there are other Lisp languages implemented on the JVM, I think Clojure does the best job of integrating with Java.
There are times when the Java language itself gets in the way of writing tests for Java code (including "traditional commercial programming"). (I don't mean that as an indictment of Java -- other languages suffer from the same problem -- but it's a fact. Since the topic, not Java, I won't elaborate. Please feel free to start a new topic if someone wants to discuss it.) Clojure eliminates many of those hindrances.
Lisp can be used anywhere you use traditional programming. It's not that different, it's just more powerful. Writing a web app? you can do it on Lisp, writing a desktop application? you can do it on Lisp, whatever, you can probably do it on Lisp, or Python, or any other generic programming (there are a few languages that are suited for only one task).
The biggest obstacle will probably be acceptance of your boss, your peers or your customers. That's something you will have to work with them. Choosing a pragmatic solution like Clojure that can leverage the current install base of Java infrastructure, from the JVM to the libraries, might help you. Also, if you have a Java program, you may do a plug-in architecture and write Clojure plug-ins for it and end up writing half your code in Clojure.
Not a reason but (trivial) AutoCAD has LISP & DCL runtime support. It is a convenient way to write complex macros (including ActiveX automation) if you don't want to use VBA or their C++ or .NET SDKs, or if a DIESEL expression doesn't cut it.
A lot of AutoCAD's functions are actually LISP routines.
This is a topic i myself have pondered for a while but I have not really come to a decision, as usual time is the main problem... ;)
And since I can´t find these links sofar in this post i add them for public interest:
Success and Failure story:
Lisping at JPL
Really impressive success story:
Lisp in use at the Orbitz corporation
Comparison and analysis of whether to use Lisp instead of Java:
Lisp as an Alternative to Java
Syntax is irrelevant, readability is not!
Not saying this is a killer app but it looks like it could be cool
http://code.google.com/p/plop/
Killer app? The flight search engine by ITA Software is one.
As for "why", it will most probably make you a better developer and is extremnely unlikely to make you a worse one. It may, however, make you prefer lisp dialects to other languages.

Resources