What's so great about Lisp? : its extreme malleability in the way you write code and the data it uses.
Code and data are the exact same things in lisp. They are represented the same way : lists represented with braces around them who can be nested. It's called s-expressions and they are in the form (<operator> <operand1> <operand2> <operand3>). There is no fundamental difference between code and data they are just list represented as s-expressions:
(list 1 (list 2 3))
(+ 1 (+ 2 3))
Another example : (task
(time 14 00)
(log "beginning of task")
(job (backup-files (important-files-in (list-files))))
(job (delete (list-files))))
Quick, what's that above, code or data? How about both?The one nice thing about s-expressions (sexp) instead of classical curly braces is that the code written in sexp IS ITSELF the abstract syntax tree of that code.
For example, think of a function function add(a, b){return a+b;}
You could convert this function into its syntax tree like this :
(define-function (name add) (parameters a b)
(body (return (+ a b))))
If we simplify things a bit we end up with : (defun add (a b)
(+ a b))
Lo and behold, the example above IS Lisp code. Is that code or data? How about both?The syntax of Lisp is the same as its internal represention. That's called homoiconicity.
What's so great about that? Well, mix that with macros whose language is Lisp itself and can do anything with s-expressions and you end up wielding great powers.
A simple example. Let's go back to our task example. We can treat it as data :
//not actual lisp code but you get the point
var my-task = (task
(time 14 00)
(log "beginning of" )
(job (backup-files (important-files-in (list-files))))
(job (delete (list-files))))
my-task is now a list containing sub lists representing a task.
What if we did this now : //not actual lisp code
(defun time (hour minutes) (print "%d:%d" hour minutes))
(defun log (string) (print string))
//we say that task is a function
//that should call each list it contains as a function
(defun task () /*execute each list it contains*/)
//...
Now we can just do: (my-task)
What do you think is going to happen? Yes, the data, the task is being executed.Now for the last touch : add to Lisp a powerful macro system that can take any s-expression (any list) and transform it any way it see fits and you end up yielding great power. What's that language? It's Lisp itself. Code is data. Lisp code evaluting other lisp code. I am so enlightened.
Not enlightened? Didn't get anything out of my post? Then give Lisp a try! You have to dive into Lisp to be able to get it. As Eric raymond put it : "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." - ESR