Hacker News new | past | comments | ask | show | jobs | submit login

I use lisp in a commercial setting.

The main point about lisp is 'there is no accounting for taste'.

Lisp leaves most things up to the programmer's taste.

You can write Lisp that looks like Fortran, or C++/Java, or Scheme.

You can make a DSL that directly models the problem.

You can use objects or no objects, do everything in CLOS or do everything with structs.

You can write your own object system.

You can make it fast or slow, you can use correct data structures or you can do everything with lists.

You can use macros for everything or you can never touch macros ever.

You can make your program one big macro.

None of these things are 'bad taste.'

Most people have different taste from you.

Most people only end up learning the part of the language consistent with the paradigm that they like.

If you only know that piece of the language, you will have difficulty working on someone else's project when they are working in a different paradigm.

None of the individual pieces of the language are particularly difficult.

People complain macros are difficult to understand. Macros are easy. If you can understand a program that concatenates lists to make a new list, you can understand a macro. Macros are quite literally 'just lisp code'.

Are some macros written in a way that you can not personally understand? Most likely, but that is not an issue inherent to macros. You have to be careful about checking inputs, and creating the proper debugging and type checking at macro-expansion time. Just like any other program. There does seem to be a stupid tendency for people to cram an entire macro into a single function. This is foolish, the whole point is that you have the entire power of this lisp runtime. There is no reason to write it like c pre-processor garbage.

So, how does one write good lisp code? Well, one way is to pick some standards. This is as difficult has having someone in charge willing to gently say 'this doesn't really match up with the style of the code around it'. If I've inherited some code, when I do a bug fix, I'm going to do my damnedest to stick with the style that it is written in (unless it is truly tagbody/go awful, in which case I might rewrite).

This kind of turned into a rant, I apologize. I guess my point is that sure, lisp is powerful, but the real issue is the number of options that it provides. At some point, you have to pick a subset and a style, and go with it. And then you have to be comfortable learning if you inherit something that you don't know yet.




Lisp leaves most things up to the programmer's taste.

I don't entirely disagree, but I think there's more to it than that. While the language certainly does offer some free choices, more often there are advantages and disadvantages to each, so that in any particular situation, some choices are better than others. Becoming an expert Lisp programmer requires learning about these tradeoffs, which takes experience and, usually, guidance from existing experts.

That's true of any language, of course, but some of the facilities Lisp offers are rare among other languages, so that people coming to Lisp from some other language are unlikely to have experience with them.

Oh, one point about macros in particular. If you have to resort to reading the implementation of a macro to understand what it does, the person who wrote it screwed up. Macros should always have documentation strings explaning their syntax and semantics. If you find yourself in that situation, the best thing to do is to go to the REPL and use `macroexpand' interactively to see the expansions of the macro calls you're interested in.


I don't entirely disagree, but I think there's more to it than that. While the language certainly does offer some free choices, more often there are advantages and disadvantages to each, so that in any particular situation, some choices are better than others. Becoming an expert Lisp programmer requires learning about these tradeoffs, which takes experience and, usually, guidance from existing experts.

There is a saying 'perfection is the enemy of done.' In any particular situation, there is probably not a solution that is both optimally efficient and also optimally elegant. (This is true in any programming language). If you work towards that goal too much, you will likely miss your deadline.

But the point is, the little advantages and disadvantages don't matter until they do. There isn't going to be a big difference in most programs between using a loop to iterate a sequence, and using map nil with a lambda, and using do* (for example). In fact, whether there is any difference at all in the resultant assembly or byte code will depend entirely on the compiler implementation. It is a style thing... so try to be consistent, and work within what you are comfortable with.

That's true of any language, of course, but some of the facilities Lisp offers are rare among other languages, so that people coming to Lisp from some other language are unlikely to have experience with them.

Currently, the only thing I can really think of that is actually really unique is the macro facility (and that is only because, as soon as a language adopts the macro facility, it becomes a lisp.

As a programmer, the focus of my job is learning new things. I am basically a mechanism for translating the new things that I have learned into computer code. If I can't learn a few measly language features, what good am I going to be as a 'thing I just learned to computer' translator. And like I said, use what you are familiar with, until you are faced with something someone else wrote, or you have the time to learn new things. But don't punt.

If someone doesn't have experience with a given piece of the language that has been used, I expect them to pick up a book or online resource about it (and then, possibly most importantly, play with it). It is not hard, but it does take effort. There is nothing in common lisp that requires genius level intellect. (God knows, I'm certainly not that bright). No one requires that fresh-faced C interns be pointer arithmetic gods, but i'm sure they are expected to learn it if it is part of the job.

Oh, one point about macros in particular. If you have to resort to reading the implementation of a macro to understand what it does, the person who wrote it screwed up. Macros should always have documentation strings explaning their syntax and semantics. If you find yourself in that situation, the best thing to do is to go to the REPL and use `macroexpand' interactively to see the expansions of the macro calls you're interested in.

I'll add that in addition to doc strings for syntax and semantics, there should also be assertions written into the macro about the syntax and semantics. If I am passing a number or list where the macro is expecting a symbol, an error should get thrown during the macro-expansion phase. Macros are programs like anything else. Validating inputs and throwing an error at the earliest possible time is a good rule to go by.

So, macroexpand-1 is a good start, if the macro is implemented correctly, does what its documentation says, and you are simply flubbing the syntax. (Of course, it should be yelling at you for flubbing the syntax).

However, when there is a bug in a macro, the only thing that macroexpand-1 will tell you is that the macro doesn't work. You'll macro-expand it and say 'yup that's the wrong generated code.' It doesn't really tell you anything about how to actually fix the macro unless you are already familiar with the macro's code. Having examples of inputs with bad outputs will aid in pinpointing the problem, but not unless I already understand how the program works.

Macros are lisp programs, and can be as complicated as any arbitrary lisp program. Writing a more complicated macro is not screwing up (I think this is an important distinction to make)... inadequately documenting, explaining, and bulletproofing it is. Someone might have to debug it later, so strive to write readable macro code. It isn't hard as you are just constructing lists and writing normal lisp code with minimal efficiency requirements.

So I guess that was a roundabout way of me saying "I agree, mostly."


That's really helpful -- nice to hear from a pro. Thanks.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: