A lisp program's code can be manipulated by the program itself. Lisp programs are self-aware.
It's a bit mind-bending, but from this simple foundation comes the power to easily create and assimilate ever higher-level abstractions (which is what programming is really all about). Parts of a program can be used as a template for creating other parts as needed. You can assemble these parts and shape the language into something very specific for the problem you are solving.
Other languages come part-way, but don't fully embrace this concept (code=data) because it has a cost: it seems difficult to learn because it requires a change in thinking; it seems difficult to write (and read) because you're directly encoding a data structure and it all looks a bit 'samey'. Where other languages have 'shapes' in their code that give the trained eye an indication of what the code is expressing (such as for...do loops and indentation), lisp code has one shape: a tree [1].
I don't know if I've reached beyond your understanding. I haven't meant to, but the takeaway should be this: lisp programs are self-aware and can operate on themselves because a lisp program is just data like any other. This makes it easy for the interpreter/compiler (hence 'lisp in x lines of code'), but more difficult for the programmer (at first). As with all things, practice and familiarity overcome these initial difficulties. It is worth it.
This is a really good explanation, and I just want to add a small bit to it, having had to use Lisp as a primary language quite recently due to some AI projects in cognitive modeling. One thing that I've found personally is that by understanding Lisp, you can essentially gain a deep understanding of every __other__ programming language.
If I had the chance to do my entire Computer Science career over again, I would have learned Lisp as my first language, and then compared every other subsequent language against it. Because of the deep symmetry between code and data, it is one of the easiest languages for implementing and re-implementing programming language features on top of.
I know a bit about programming but it only comes down to PHP or jQuery variables, functions, and loops. Lisp looks very interesting and I had already heard about it (through pg obviously). It might just be the language that will fascinate me if I ever took programming more seriously.
Chess has relatively simple rules (initial board layout, legal moves, win condition, some fanciness with en passant and castling, etc), but the game is endlessly complex, and there are more boards than a human being could ever see in his or her lifetime. Lisp is similar in that regard.
I'd say comparing it with Go might be easier, it has 8 rules, and can be played on a board of any size. I like to compare that to the 10 commandments in "The Little Schemer" or the 9 functions in μLithp.
Could you explain how Lisp can be simple and powerful?
You've asked a profound and important question, not so much about Lisp as about systems in general. A system is simple when it doesn't have many pieces. But if the pieces it starts with are very general, and the system provides good ways to put them together, then you can build complex things out of a tiny initial set.
Think of a classic Lego set. There are only a few "primitives" (different kinds of Lego piece). And there is an easy and standard way to put them together. Starting from these simple initial conditions you can construct very complex structures. Lego is simple and powerful at the same time.
How do you build a complex Lego structure? You start by putting a few pieces together to form a cluster. And then you make a second cluster and you join the two clusters together to make a third, and so on. The critical property here, the reason why Lego stays simple all the way, is that the "operation" you use to join two clusters is exactly the same operation you use to join two individual pieces – you interlock their knobby bits. In this sense your clusters are still "Lego pieces", just custom ones that didn't ship with the initial set: they still have knobby bits suitable for joining up with any other piece. This quality is sometimes called "regularity", meaning that the initial properties of the system are preserved as you put things together into ever more complex forms.
Suppose that weren't the case and that each time you reached a certain level of complexity you had to learn a new technique for building further. That would make Lego much less simple-and-powerful. You could still build complex things, but it would be harder and more complicated. And there would probably be a bunch of things that, while you technically could build them, it would be so hard and complicated to do that nobody would bother.
Programming languages also consist of a set of initial pieces and ways of putting them together. But most languages don't have the quality of regularity that Lego has. Their initial pieces aren't universal enough to get away with having only a few, so they need many more of them, and that means they're not simple, and that means they're not simple-and-powerful. There are, however, a few programming languages that do have this regularity. Lisp is one of them. Smalltalk, Forth, and APL are others.
The really interesting thing is that this kind of simple-and-powerful system enables you to do qualitatively different things as complexity grows — not because other languages can't do them, but because they make it too much trouble to bother. For example, because Lisp programs are Lisp pieces in the same sense that Lego structures are Lego pieces, it's easy to write Lisp programs that take other Lisp programs as their inputs and do meaningful things with them. That is a powerful technique, and because it's so easy, Lisp programmers exploit it heavily, more than is practical in most other languages, and that means they can do more with less.
This quality of simple-and-powerful is in my view very important and underutilized for managing software complexity. We don't yet understand it all that well, because the programming languages that achieved dominance to date don't have it.
Lisp is very simple and very powerful. Those who don't learn it are doomed to reinvent it, badly (cough XSLT cough).