Hacker News new | past | comments | ask | show | jobs | submit login
Google's Common Lisp style-guide (googlecode.com)
178 points by zaph0d on Oct 11, 2012 | hide | past | favorite | 57 comments



This must have come out of the ITA Software acquisition.... (Heading "Attention required" 'You must follow the ITA convention of using...') They were a big common lisp user apparently.

Google is normally very specific on the languages allowed for internal projects. A product/company acquisition with large assets written in common lisp would necessitate this becoming the "Google Common lisp style guide" rather than what it was most likely originally the "ITA Software" common lisp style guide. Speculation of course, but looks likely.


>This must have come out of the ITA Software acquisition

One of the authors, the one that goes by the name Faré, definitely came with the ITA acquisition.


ITA continues to be heavy users of Common Lisp.


Do you know this for a fact? That'd be quite impressive if the Lispers maintained strong against Google's policies.. I remember reading that they ported over


I oversaw development at ITA for many years and can tell you the probability that they're going to port QPX to Java is nil. (Or perhaps NIL.)


On the contrary, it would be impressive if Google managed to make them port half (or more of) their codebase from Lisp to Java and still keep the ITA employees, some of whom are hardcore lispers.


I have a friend who works for ITA/Google today, and he tells me they are still using Lisp and their Lisp codebase is huge and complicated and not likely to ever be ported to another language.


That's awesome -- so with them publishing this style guide, are they trying to reach out to the Lisp community for recruitment purposes?


Lispers tend to be a clever bunch. I'm quite sure they can be very convincing.


ITA has been writing Java for almost 10 years for their website.


A very useful document that I mostly agree with.

One area of difference is in the conditionals. I never use WHEN or UNLESS for value; only for effect. And, I never write NIL as one of the values returned by IF; I always condense the expression to AND or OR. That is, I freely use AND and OR to return non-boolean values; this is a practice some deprecate, and indeed, I'm surprised not to find it explicitly mentioned here.

I do like to write certain kinds of iteration as tail-recursions, but I always use local functions (LABELS) when doing that; there's no implementation I use regularly that doesn't do tail-call optimization on local calls.


Using AND and OR to return non-boolean values is one of the best, most useful parts of Common Lisp.


This further reinforces how Yegge's recent "software political axis" rant was wildly inconsistent. His characterization of Clojure was "highly conservative" based in part on the best practices avoiding macros when possible, unlike "liberal" languages including Common Lisp.

Meanwhile in his own company's coding style for Common Lisp states very similar best practices regarding macros -- they should be used "sparingly and carefully", "You must never use a macro where a function will do.", etc. The whole macros section basically reads as a list of well thought out reasons against using macros when writing code that other people will have to maintain.

Yegge: "I trust that if you know anything about Lisp, your blood is basically boiling at this point." Really? Well then maybe the google CL team doesn't know lisp or otherwise are looking for novel ways to escalate their collective blood pressure.


Disagree, this advice regarding macros is mainstream Common Lisp thought. It's certainly been repeated enough on #lisp.

And, ah, the google CL team is, AFAIK, the former ITA, which was one of the top known Lisp shops worldwide. They know their Lisp.


No, Steve's rant was also about how Google is very much on the "Conservative" end of the political spectrum. When a conservative company uses an - as per steve's article - liberal language, you can't expect them to use it in a liberal way. The story checks out.


I disagree. The Common Lisp community commonly has had the advice to be sparing with macros. Dan Weinreb (of ITA and the Common Lisp standard) mentioned this about ITA pre-Google. Paraphrasing from memory, "You can use functions anytime. With macros you need justification. With reader macros, you need a LOT of justification."

The conventional advice is not to go nuts with macros. In normal Common Lisp code, you don't need to write many macros. And when you do, they're typically with- macros.

Now, you can be a heavy consumer of macros. That's something else. Like using the LOOP macro all the time, for instance. The DEF... forms too. If you're building a powerful new abstraction, like OOP or the metaobject protocol, then it's great to have powers normally reserved for language designers.

Also, see Rich Hickey's points: (http://news.ycombinator.com/item?id=4366661)


> Meanwhile in his own company's coding style for Common Lisp states very similar best practices regarding macros -- they should be used "sparingly and carefully", "You must never use a macro where a function will do.", etc.

This is not arguing against macros, per se. The most powerful feature of macros is controlling how / when arguments are evaluated. So, if you don't use a macro when a function (i.e. standard arg evaluation) will do, you're not missing out on the power of macros.


Yegge is wrong about this. It is generally accepted in the Common Lisp community that you avoid macros whenever possible. Here's a quote from pg's "Beating the Averages"

"Macros are harder to write than ordinary Lisp functions, and it's considered to be bad style to use them when they're not necessary."



I've often thought that stylistic (as opposed to semantic) formatting rules should be enforced by pre/post commit scripts or nanny scripts.

This would be a huge pain with hard-to-parse languages like C++, but might work a lot better for C / ObjC / CL / Java.

Just put your braces wherever they make you feel special, and let the formatter sort it out.

Anyone do this?


Go famously comes with gofmt for exactly this reason.


I do this in Python-land. There's a tool called 'pep8' named after the community sanctioned style-guide of the same name. Before I push any changes I have a script that runs my tests and the pep8 script. It's more of a backup-measure in my case since I have my editor run pep8, lint, and my unit tests constantly.


Indeed, and combining it with pyflakes makes for a great combo, ensuring that code you commit both looks generally correct, and passes basic sanity checks.


I do this with perl. I use emacs' cperl mode, but I have Ctrl+x t bound to perltidy-buffer, which formats everything for me. I've modified the rules slightly (people at my work like tabs instead of spaces) but I tend not to spend too much time worrying about stylistic formatting rules.

Of course, this does not apply to some areas of vertical white-space, which I still have to manage myself.


We do this at Google, though humans are responsible for actual enforcement -- you can check in code even if it has lint errors, but your code reviewer should tell you not to. (For things like build files, though, you can't check in code with lint errors. That just saves everyone time and frustration.)


We have a script to autofix these issues. Interestingly enough the only things I would give a shit about are those that can't be fixed manually (e.g missing comments).


astyle works fine with c++


"Everybody's code should look the same. Ideally, there should be no way to look at lines of code and recognize it as "Fred's code" by its style."

This is how one endeavors for mediocrity within a creative pursuit. Crap gets polished to a bronze sheen.


The key words here are "by its style". There's still plenty of room for creativity in how you structure the code, how you approach solutions, etc., which is where the creativity belongs. Mediocrity is not overcome with creative spacing.


I would prefer that the creativity in software development does not come from where you put your parenthesis or spaces. The creativity is in the solutions.


That argument doesn't make sense. My outlet for creativity is the content of my code not when new lines happen or how I indent. On the other hand, if everything in the codebase is formatted uniformly it's a lot easier to scan through and you don't end up with diffs filled with reformatting kruft as each team member walks over the others' formatting style.

If you're feeling extra creative, you could always change your font, font size, and syntax highlighting scheme. ;)


He could quote a better example, but I think the document goes deeper than just formatting style.

From the article's excerpt "Principles":

* Don't be "clever" — do the simplest thing that could possibly work properly. * Be precise. * Be concise. * KISS — Keep It Simple, Stupid. * Use the smallest hammer for the job.

---

They are indeed asking for uniformity against creativity. Which is not a bad thing for corporations (IBM have very strong guidelines for years) but definitely takes away that "hacker" aura that we gave to Google a few years ago.

Any googler that can put this in context?


> They are indeed asking for uniformity against creativity

Well, I mean you could argue that this is clever, creative and beautiful ( http://thedailywtf.com/Articles/Confessions-rachetingDateObj... ). To quote one of the comments "If I lean close enough to the PC's speaker, I can hear the tiny clicks of all those wheels spinning round - 'sbeautiful."

I don't think google is really arguing against creativity, rather saying "don't be creative for creativity's sake".

I remember having to install Quartz Scheduler so it would hit a single servlet every night at 1am. That's _ALL_ Quartz was used for. When I asked about using cron the response was "well that wont scale"... this application had been around for fifteen years and during that time there was only one batch process... clever indeed!


There always would be anecdotal cases and interpretations. That's why I asked an open question to a googler who could set the document into a context.

I also have cases of people doing a lot of ad-hoc code because it was easier (small hammer to the job) and then resulted in a pain code to read that could be prevented with a clever system. But I am agreed with you that the whole thing is arguable and subjective


Which of those principles is at odds with creativity? Is verbose code positively correlated with creativity? Code more complex than required? Ambiguous code?


I already told in another reply that it is subjective.

But when they say "KISS Keep it simple stupid" one programmer could interpreter that as "OK for this messages management system what is more simple than a huge list of if statements" and another one could interpreted the same principle as "Hmm OK, I will have a list of closures to reduce verbosity"


That says to not be creative just to entertain yourself. Be creative to solve problems. It is a polite way of saying "you aren't as smart as you think you are at 3am on a red bull binge". This advice was not invented by Google. Knuth or someone for one has a famous quote about it: debugging is harder than first draft, so how do you debug code that you wrote at peak cleverness?


From The Elements of Programming Style by Kernighan and Plauger: “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?”


Related: ITA Software's Carl de Marcken discussing their use of Common Lisp for Orbitz from 2001 with a 2002 update.

http://paulgraham.com/carl.html

Snippet:

  ITA Software is slowly replacing the industry's hardware 
  and software with Common Lisp code running on Linux PCs, 
  that uses relatively involved algorithms that show off 
  our academic CS background.


Yes, it looks like (besides the leftover "ITA" comment in the guide!) that this is simply the ITA guidelines. From Carl's remarks, you can tell that ITA is not a 'normal' Lisp program. Most Lisp programs do not preallocate ~5K of data structures and fail-fast if they exceed that, for example.

Compare to the more conventional Norvig style guide (who is also of course at Google today, coincidentally): http://www.cs.umd.edu/~nau/cmsc421/norvig-lisp-style.pdf (PDF)


ITA actually has two large Lisp systems. One of them is the insanely optimized fare search system (QPX) that does all the crazy things described in the link. The other is the airline reservation system which is a much more conventionally coded Lisp system.


Is this due to the acquisition of ITA Software? I though Google was not in favor of Common Lisp.


Congratulations, Robert Brown and François-René Rideau!


I'm not sure I understand/agree the point about "iteration over recursion". One of my favorite aspects of Lisp is the recursive approach to writing functions. It's still possible to write recursive functions that don't rely on a specific compiler's optimization:

(defun sum (numbers) (labels ((helper (todo ans) (if (null todo) ans (helper (cdr todo) (+ ans (car todo)))))) (helper numbers 0)))

I hope that this is what the author meant with "iterative" approach, because it is recursive by most standards.


Without TCO, doesn't your function overflow the stack, given that "numbers" is long enough? By iterative I think they mean the use of "loop" or "iterate".


I thought that Common Lisp guaranteed Tail Call Optimization (TCO), but it looks like it's actually up to the implementation: http://0branch.com/notes/tco-cl.html


Scheme guarantees it; CL only provides it as an option.


Nit pick: if it is guaranteed, call it Elimination, not Optimization, because it is part of the operational semantics required to reason about performance. As a compiler Optimization, you have an algorithm that is omega(n) space usage, but with Elimination as a language feature you have an O(1) space usage.

Yes, you can include compiler optimizations in your model of the language, but it helps to distinguish opportunitistic speedups from guaranteed complexity class improvements.


I think they consider that recursive.

However, all the major implementations (SBCL, Clozure CL, Franz Allegro, LispWorks, CMUCL, and I think even ECL) do tail-call elimination on local calls. (A local call is a call to a function whose definition is lexically visible, such as the calls to 'helper' in your example.) The document says that TCE depends on optimization settings, but for local calls, I'm not sure even that is true. Anyway, the practical upshot, in my experience, is that there's no reason not to write loops recursively using LABELS when that is the most elegant expression of the particular loop in question.

(There was once a major implementation that never did TCE -- Genera -- but even for die-hard Lisp Machine lovers like myself, it has long since been relegated to a historical curiosity.)


Thanks for that Scott, I've never heard of TCE -- learn something every day reading HN.

Just did a quick comparison (SBCL) between the above and the textbook version:

(defun sum (list) (if (null list) 0 (+ (car list) (sum (cdr list)))))

This version quickly dumped Heap Exhaustion. The LABELS version does not, and can handle summation over lists much faster as well.

What does this mean? TCE only applies applies to local calls, therefore we should never write a "raw" recursive function? (which is a tad more elegant, imo). I haven't delved into TCOs deep enough to understand, but I had hoped that a smart compiler would be able to optimize the latter?


Why is the content buried under a million collapsed arrows?

Should "grammar nazi" have a capitalized "N", or should the term be avoided in a Style Guide?


About your second question, I like the following advice: "I would recommend lowercase, if you are not actually referring to the Nazi party, its members, or principles."

http://english.stackexchange.com/questions/73948/grammar-naz...


there is a large triangle button at top of the page with text "Toggle all summaries" next to it.


+1 exactly right. I clipped this article to Evernote and had to toggle all summaries visible first.

BTW, that is a great style guide, and mostly how I code in CL.


...is there any place one can find a list of companies/projects using CL and specifically what they do with it? ..or of open source projects using CL? (or do people still treat it as "our secret sauce")


You may find what you're looking for on either the ALU wiki (http://wiki.alu.org/) or the CLiki (http://cliki.net/)


good one




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

Search: