Hacker News new | comments | show | ask | jobs | submit login
Ask HN: Why does learning lisp make you a better C-programmer?
25 points by morphir on Jan 25, 2010 | hide | past | web | favorite | 17 comments
from Eric Raymonds essay, How to become a hacker:

LISP is worth learning for a different reason — 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.

However, I want concrete examples (methodologies)

Ok, here is one:

Lisp makes you think in terms of higher level memory structures than just other than bytes and pointers to structs.

The 'lists' and all the operations that you can perform on them will initially feel terribly inefficient (filter??!), but this will literally free you from having to think about how stuff is laid out in memory.

The upshot of that is that you will see more clearly what the real solution is to your problem.

As for functional programming, that in and of itself is a great way to get an alternative look at your programming.

For a fantastic example of that look at the 'hashlife' code, it's written in C but it could only have been done by someone with a profound insight in to the benefits of functional programming.

The reverse is also true, learning C as a lisp programmer will make you a better lisp programmer.

In fact I doubt that there is any language that does not have to contribute some unique bit to the world of programming, and that will enrich you if you learn it to some level of proficiency.

Others have already taken your challenge on directly, and that is a part of the truth. However, I want to point out that if you want, you can sit and nitpick each one, pointing out how C is just fine on that front, and talk yourself into a position where it's not that big a deal, by focusing on one thing at a time and appearing to knock out each thing one by one. For this reason, "enlightenment experiences" tend to resist concretization; focus on just the words and you can talk yourself right out of them without much effort.

But the point is not the laundry list of bullet-point features, the point is the whole totality of the experience. There isn't a thing that Lisp can do that C can't be beaten into doing; for one thing, writing your own Lisplet isn't that hard (and a good exercise, too!), and there you have it, "all of Lisp" right there. But it makes those things so hard that you won't really want to do them. You can intellectually learn the value of some of the things that Lisp provides, but until you live for a while in an environment where they are easy you will never fully grok them.

Even though Lisp teaches nothing that could not be theoretically learned in C, in practice you won't learn them in C. The bar is too high, and if you're really trying to do it from scratch you'll make too many mistakes on things that were worked out 40 or 50 years ago. Learn something like Lisp.

(Haskell is another choice on that front; Lisp will teach you better metaprogramming, but Haskell has some advantages in forcing you to completely follow through with an alternate paradigm. Arguably Lisp is more practical for permitting such things, but less educational.)

Learning new languages makes you a better programmer. It really has very little to do with C or Lisp specifically.

The more different the language you are learning is from ones you have used in the past, the more new approaches you learn. For instance if you already know C++, you'll learn a lot less from learning Java than you would if you learned Lisp (or ML, or Haskell, or Smalltalk) - purely because the delta is much larger. Similarly, if you already knew Ruby you'd probably learn fewer new techniques learning Smalltalk than Haskell, and if you already grok Scheme you'll learn very little from Common Lisp.

If you are a C hacker, and especially if C is your first and primary language, Lisp just happens to be on the far other side of the wheel of languages, so you'll learn a heck of a lot from it. I would wager that learning C would make a Lisp hacker better at Lisp, too, though I don't know anyone for whom Lisp was a first language.

Here is an example of a programmer who was able to produce a much more efficient and reliable C program by applying principles he learned in a Scheme course:


Now, this may not be exactly what you're looking for, in that the C code he ended up with is not what you would call idiomatic C, so whether it made him a better C programmer per se is debatable. But doubtlessly few of his classmates were writing idiomatic C either, and his program's performance and reliability would not have been possible if he hadn't worked through the problem in Scheme first.

(Edit: The closing paragraph, in particular, illustrates the broadly applicable "profound enlightenment experience" that Eric Raymond describes.)

Thinking functionally you C better.

I want a pony.

Learning a new language- truly learning it- puts quux in your brain. Those quux are unique to that language. You can try to make do by translating the meaning of those quux into your favorite language, but the fact is that "gravitas" doesn't really mean "formality in bearing", so there's some difficulty in working that way.

Consider recursion: Generally accepted you can simulate it with stacks and lists, the recursion quux is very powerful because binary tree traversal is simply walk(t){walk(t.left);walk(t.right);}

Recursion is available in many languages, but not all languages. In those languages an expert programmer won't have the quux for recursion and you'll see lots of arrays and array resizing as the programmer simulates recursion when it is needed- and terrible contortions when the function can be implemented without recursion.

Without knowing more about your background, it is difficult to give a better example than that. If you know Java and perl, this is why Java programs written by a perl programmer look strange to a Java programmer: The perl programmer is using "perl quux" to work out the program in their head, and is translating them to Java syntax and grammar. I suspect that you've seen other examples you can use here.

The important bit: Lisp has a powerful quux in it; it is powerful because it reduces huge problems to much simpler problems. Learning lisp (or inventing it independently) is the only way to get that quux in your brain.

However here's hope: Once that quux is in your brain, you won't see parenthesis anymore.

You will at least be able to recognize the symptoms of Greenspun's Tenth (http://lispers.org/) in your C code and know when to cut your losses in those cases when C is not the best possible fit to the problem domain at hand.

for my money, this is the best argument here.

c memory handling is so painful, and support for higher order functions so limiting, that there really is very little that you can carry across directly from lisp and/or functional programming to c. on the other hand what you do see, is how much time you are wasting due to c's constraints; something that may help you better allocate your time and/or choose your tools.

there are other small wins too. sometimes knowing the "easy way" to solve a problem you can then work out a compromise in c that gives you some of the benefits without being too hard to implement. as a result you can end up using realloc much more than other people you work with :o)

Lisp dramatically lowers the bar to make a compiler. You don't have to mess with parser generators and do complicated parsing, the Lisp reader and s-expressions already provide a ridiculously simple and powerful framework to make your own syntax and semantics.

You can easily invent your own language, basically you can just represent the structures of your language as objects and then walk that structure to generate a tree of closures that represent the semantics, the code to execute. With a compiler, you can give your language very "special" semantics and performance isn't adversely affected (it might in fact be better). What's more, if your custom language is very declarative, really close to what you actually mean to say, your "programs" written in that language is actually useful data you can use to make high-level debuggers and such.

And for generating that tree of objects in the first place, you can use macros to make a nice s-expression representation that expands into object instantiations instead of having to do objects manually, which is harder to both read and write.

If you try this, you'll see that languages really are not that magical, that it's within your reach to design and implement one even without investing hundreds of hours in learning arcane skills, if you use the right tools.

I came to understand and appreciate exceptions better, once I learned how they were implemented in Common Lisp. The same goes for macros, multiple-values, dynamic binding, closures, multiple-dispatch, the REPL, and many other things.

Not all of them are available in C/C++, but in one form or another they could be done.

The biggest revelation for me was the most of the C++ patterns, are just weaknesses of what the language can express. This made me free of what was expected as norm in C++, and I came to appreciate just C more and more (being more simpler).

In every art there is a dichotomy between the practical and the theoretical, and each has their fundamentals. In Comp. Sci., those two sets of fundamentals are these: sets of machine instructions, which come in several varieties; and lambda calculus, or one of the equivalent (by Church's Thesis) formal systems. C and Lisp are similar in that they represent the first steps in each case to reach the other: C is a level above machine code, providing some abstraction and portability to the use of machine code, the fundamental elements of practical computing; lisp is a level above lambda calculus, providing a practical system for using functions, the fundamental elements of theoretical computing.

In short, mastery of C is concomitant with the ability to measure the cost of computation (sometimes, regardless of the value of it); mastery of Lisp is concomitant with the ability to measure the value of computation (sometimes, regardless of the cost).

Since C and Lisp lie on opposite borders of the universe of computation, knowing both will allow you to better measure the scope of that universe.

There are counterexamples too. I feel like my C has gotten worse in some ways (and not for lack of practice) because of Lisp -- I tend to make more expressions and assign fewer temporary values. C code often benefits in clarity from named temporary variables, but my Lisp style tends to eliminate them.

Don't fall into the trap of listening to Eric Raymond too much. He likes to romanticize the whole thing too much, as this quote kind of demonstrates.

That said, let me echo some of the other posters: Learning any new languages will improve your skill in all languages. Even if the only benefit you get out of learning Lisp is a better understanding of recursion and linked lists, you win. There is also a great deal of satisfaction for a newcomer in writing a good solid Lisp routine, because you're thinking it'll never work, and then it works perfectly.

Where C is so close to the machine you can taste it, for example structs and pointers, and I love it for that, Lisp is quite far away. Maybe Lisp is also useful to pull your head out of the MMU and think at a little higher level.

lisp doesn't make you a better C-programmer, It make you a better programmer becouse It make you think in a more high level abstractions (I am removing the "C"). learning Assembler may make you a better (efficient) C-programmer.

Learning something new makes you better at things you already do (if it doesn't, it's not worth learning).

Perhaps part of it is that you will no longer feel the need for methodologies?

When programming lisp, the syntax is so regular that the patterns in your code become very obvious. When I see patterns I pull them out into macros or high-order functions, and name them. (Then sometimes I see patterns in the macros/hofs, and I pull those out and name /them/).

I personally /boggle at the guys who love 'design patterns' and the like. I mean, I understand the utility of using patterns in software, I do it all day.

The problem is that only having maybe 23 (?) different patterns seems very limiting to me.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact