Google Common Lisp Style Guide

Revision 1.28

Robert Brown
François-René Rideau
In memoriam Dan Weinreb

Patterns mean "I have run out of language." — Rich Hickey

Each style point has a summary for which additional information is available by toggling the accompanying arrow button that looks this way: . You may toggle all summaries with the big arrow button:

Toggle all summaries
Table of Contents

Important Note

Note: Displaying Hidden Details in this Guide

link
This style guide contains many details that are initially hidden from view. They are marked by the triangle icon, which you see here on your left. Click it now. You should see "Hooray" appear below.

Background

Common Lisp is a powerful multiparadigm programming language. With great power comes great responsibility.

This guide recommends formatting and stylistic choices designed to make your code easier for other people to understand. For those internal applications and free software libraries that we develop at Google, you should keep within these guidelines when making changes. Note however that each project has its own rules and customs that complement or override these general guidelines; the speed-oriented QPX low fare search engine notably has a very different style and feel from the QRes reservation system.

If you're writing Common Lisp code outside Google, we invite you to consider these guidelines. You may find some of them useful where they don't conflict with other priorities you have. We welcome remarks and constructive feedback on how to improve our guide, and on what alternate styles work for you and why.

This guide is not a Common Lisp tutorial. For basic information about the language, please consult Practical Common Lisp. For a language reference, please consult the Common Lisp HyperSpec. For more detailed style guidance, take (with a pinch of salt) a look at Peter Norvig and Kent Pitman's style guide.

Meta-Guide

Must, Should, May, or Not

link
Each guideline's level of importance is indicated by use of the following keywords and phrases, adapted from RFC 2119.

Permission and Forgiveness

link
There are cases where transgression of some of these rules is useful or even necessary. In some cases, you must seek permission or obtain forgiveness from the proper people.

Conventions

link
You MUST follow conventions. They are not optional.

Old Code

link
Fix old code as you go.

Future Topics

link
There are many topics for additional standardization not covered by current version of this document, but deferred to future versions.

General Guidelines

Principles

link
There are some basic principles for team software development that every developer must keep in mind. Whenever the detailed guidelines are inadequate, confusing or contradictory, refer back to these principles for guidance:
  • Every developer's code must be easy for another developer to read, understand, and modify — even if the first developer isn't around to explain it. (This is the "hit by a truck" principle.)
  • 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.
  • Be precise.
  • Be concise.
  • KISS — Keep It Simple, Stupid.
  • Use the smallest hammer for the job.
  • Use common sense.
  • Keep related code together. Minimize the amount of jumping around someone has to do to understand an area of code.

Priorities

link

When making decisions about how to write a given piece of code, aim for the following -ilities in this priority order:

  • Usability by the customer
  • Debuggability/Testability
  • Readability/Comprehensibility
  • Extensibility/Modifiability
  • Efficiency (of the Lisp code at runtime)

Architecture

link
To build code that is robust and maintainable, it matters a lot how the code is divided into components, how these components communicate, how changes propagate as they evolve, and more importantly how the programmers who develop these components communicate as these components evolve.

Using Libraries

link
Often, the smallest hammer is to use an existing library. Or one that doesn't exist yet. In such cases, you are encouraged to use or develop such a library, but you must take appropriate precautions.

Open-Sourcing Code

link

If you write a general-purpose library, or modify an existing open-source library, you are encouraged to publish the result separate from your main project and then have your project import it like any other open-source library.

Development Process

link
Development process is outside the scope of this document. However, developers should remember at least these bits: get reviewed, write tests, eliminate warnings, run tests, avoid mass-changes.

Formatting

Spelling and Abbreviations

link

You must use correct spelling in your comments, and most importantly in your identifiers.

When several correct spellings exist (including American vs English), and there isn't a consensus amongst developers as which to use, you should choose the shorter spelling.

You must use only common and domain-specific abbreviations, and must be consistent with these abbreviations. You may abbreviate lexical variables of limited scope in order to avoid overly-long symbol names.

Line length

link
You should format source code so that no line is longer than 100 characters.

Indentation

link

Indent your code the way a properly configured GNU Emacs does.

Maintain a consistent indentation style throughout a project.

Indent carefully to make the code easier to understand.

File Header

link

You should include a description at the top of each source file.

You should include neither authorship nor copyright information in a source file.

Vertical white space

link
Vertical white space: one blank line between top-level forms.

Horizontal white space

link
Horizontal white space: none around parentheses. No tabs.

Documentation

Document everything

link
You should use document strings on all visible functions to explain how to use your code.

Comment semicolons

link
You must use the appropriate number of semicolons to introduce comments.

Grammar and punctuation

link
You should punctuate documentation correctly.

Attention Required

link
You must follow the convention of using TODO comments for code requiring special attention. For code using unobvious forms, you must include a comment.

Domain-Specific Languages

link
You should document DSLs and any terse program in a DSL.

Naming

Symbol guidelines

link
You should use lower case. You should follow the rules for Spelling and Abbreviations You should follow punctuation conventions.

Denote intent, not content

link
Name your variables according to their intent, not their content.

Global variables and constants

link
Name globals according to convention.

Predicate names

link
Names of predicate functions and variables end with a "P".

Omit library prefixes

link
You should not include a library or package name as a prefix within the name of symbols.

Packages

link
Use packages appropriately.

Language usage guidelines

Mostly Functional Style

link
You should avoid side-effects when they are not necessary.

Recursion

link
You should favor iteration over recursion.

Special variables

link
Use special variables sparingly.

Assignment

link
Be consistent in assignment forms.

Assertions and Conditions

link
You must make proper usage of assertions and conditions.

Type Checking

link
If you know the type of something, you should make it explicit in order to enable compile-time and run-time sanity-checking.

CLOS

link
Use CLOS appropriately.

Meta-language guidelines

Macros

link
Use macros when appropriate, which is often. Define macros when appropriate, which is seldom.

EVAL-WHEN

link
When using EVAL-WHEN, you should almost always use all of (:compile-toplevel :load-toplevel :execute).

Read-time evaluation

link
You should use #. sparingly, and you must avoid read-time side-effects.

EVAL

link
You must not use EVAL at runtime.

INTERN and UNINTERN

link
You must not use INTERN or UNINTERN at runtime.

Data Representation

NIL: empty-list, false and I Don't Know

link
Appropriately use or avoid using NIL.

Do not abuse lists

link
You must select proper data representation. You must not abuse the LIST data structure.

Lists vs. structures vs. multiple values

link
You should use the appropriate representation for product types.

Lists vs. Pairs

link
Use the appropriate functions when manipulating lists.

Lists vs. Arrays

link
You should use arrays rather than lists where random access matters.

Lists vs. Sets

link
You should only use lists as sets for very small lists.

Proper Forms

You must follow the proper usage regarding well-known functions, macros and special forms.

Defining Constants

link
You must use proper defining forms for constant values.

Defining Functions

link
You should make proper use of &OPTIONAL and &KEY arguments. You should not use &AUX arguments.

Conditional Expressions

link
Use the appropriate conditional form.

Identity, Equality and Comparisons

link
You should use the appropriate predicates when comparing objects.

Iteration

link
Use the appropriate form for iteration.

I/O

link
Use the appropriate I/O functions.

Optimization

Avoid Allocation

link
You should avoid unnecessary allocation of memory.

Unsafe Operations

link
You must only use faster unsafe operations when there is a clear performance need and you can document why it's correct.

DYNAMIC-EXTENT

link
You should only use DYNAMIC-EXTENT where it matters for performance, and you can document why it is correct.

REDUCE vs APPLY

link
You should use REDUCE instead of APPLY where appropriate.

Avoid NCONC

link
You should not use NCONC; you should use APPEND instead, or better data structures.

Pitfalls

#'FUN vs. 'FUN

link
You should usually refer to a function as #'FUN rather than 'FUN.

Pathnames

link
Common Lisp pathnames are tricky. Be aware of pitfalls. Use UIOP.

SATISFIES

link
You must be careful when using a SATISFIES clause in a type specifier.

Credits: Adam Worrall, Dan Pierson, Matt Marjanovic, Matt Reklaitis, Paul Weiss, Scott McKay, Sundar Narasimhan, and several other people contributed. Special thanks to Steve Hain, and to the previous editors, in reverse chronological order Dan Weinreb and Jeremy Brown.

Revision 1.28

Robert Brown
François-René Rideau