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.
One of the authors, the one that goes by the name Faré, definitely came with the ITA acquisition.
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.
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.
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.
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)
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.
"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."
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?
Of course, this does not apply to some areas of vertical white-space, which I still have to manage myself.
This is how one endeavors for mediocrity within a creative pursuit. Crap gets polished to a bronze sheen.
If you're feeling extra creative, you could always change your font, font size, and syntax highlighting scheme. ;)
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?
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!
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
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"
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.
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)
(defun sum (numbers)
(labels ((helper (todo ans)
(if (null todo)
(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.
Yes, you can include compiler optimizations in your model of the language, but it helps to distinguish opportunitistic speedups from guaranteed complexity class improvements.
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.)
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?
Should "grammar nazi" have a capitalized "N", or should the term be avoided in a Style Guide?
BTW, that is a great style guide, and mostly how I code in CL.