EccentricDuck wrote:Anyone with an opinion on Lisp? I've heard people go "oh, it's outdated, no one uses it, etc etc." and a select few say things like "it's made me a far better programmer" or "it's the reason I can rapidly create effective tools and software while others take several times as long with XX language". I've never really seen a good description of WHY either of those parties have those opinions though; but I would like to know since the latter group certainly have appealing positions.
Yes, I actually use Lisp at work every day. Well, I actually use Clojure, which is a Lisp dialect that runs on the JVM.
The reason people say it's made them a better programmer is that Lisp has abstractions that other languages don't, so you learn to think differently when solving programming problems.
I think the reason people say Lisp is the reason they can create software faster than in other languages is also that the abstractions are good.
The main abstraction mechanism Lisp has that other languages don't have is macros, which let's you create new language constructs by hooking into the compiler, and having your code run at compile time. See, the reason for all of the parentheses in Lisp is that Lisp code is defined in terms of Lisp lists. A List with a symbol and three number in Lisp looks like (+ 1 2 3). When this is read by the reader, it gets turned into a list data structure in memory, and is then passed to the compiler. So the compiler compiles data structures, not text. And not just any data structures, but the core Lisp data structures. In most Lisps this is just lists, but Clojure also has literal vectors and hash maps.
So...what was I getting at? Oh right, macros. Macros are called at compile time, and the arguments to a macro are passed in as code (in the form of data structures). The macro then returns data structures, which represent code, and the compiler compiles the returned code.
Here's an example. The built-in way to create a function in Clojure is
This function takes one argument, and returns the input times two. But notice this function doesn't have a name. So to give it a name, you would do
But this is kind of annoying. Wouldn't it be nice if there was a cleaner way to define a named function? Well, why not write one?
Code: Select all
(defmacro defn
[name args & body]
`(def name (fn args ~@body)))
I know you don't know exactly what's happening in the above code, but the point is that now we can use the macro 'defn':
In this example, I used a pattern syntax in the macro definition, but it could have been written like this too:
Code: Select all
(defmacro times-two
[name args & body]
(cons 'def (cons name (concat ['fn args] body))))
Anyway, the point is that you can return
any code from a macro, which can be manipulated/generated by the full Lisp language.
Lisp also has other powerful abstractions, like closures, but other languages have closures as well.
I don't know if you wanted that much of an explanation of Lisp macros
, and I probably did a bad job explaining them anyway.
If you want a better explanation, I would recommend this:
http://www.defmacro.org/ramblings/lisp.html
Anyway, the point is that I think it's worth learning Lisp. People tend to complain about all the parens, but I like the syntax. I like it because it's simple and consistent.
Also, there really aren't many more parens in Lisp than in other languages, it's just that Lisp doesn't have any of the other syntax in it.
Code: Select all
C++ function call:
someFunc(foo, bar, baz);
Lisp function call:
(some-func foo bar baz)
C++ if:
if(someFunc(foo, bar, baz))
{
return otherFunc(foo);
}
else
{
return anotherFunc(bar);
}
Lisp if:
(if (some-func foo bar baz)
(other-func foo)
(another-func bar)))
Same number of parens.