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

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

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

Permission and Forgiveness

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

You MUST follow conventions. They are not optional.

Old Code

Fix old code as you go.

Future Topics

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

General Guidelines

Principles

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

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

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

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

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

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

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

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

Indentation

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

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

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

Horizontal white space

Horizontal white space: none around parentheses. No tabs.

Documentation

Document everything

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

Comment semicolons

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

Grammar and punctuation

You should punctuate documentation correctly.

Attention Required

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

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

Naming

Symbol guidelines

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

Denote intent, not content

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

Global variables and constants

Name globals according to convention.

Predicate names

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

Omit library prefixes

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

Packages

Use packages appropriately.

Language usage guidelines

Mostly Functional Style

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

Recursion

You should favor iteration over recursion.

Special variables

Use special variables sparingly.

Assignment

Be consistent in assignment forms.

Assertions and Conditions

You must make proper usage of assertions and conditions.

Type Checking

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

CLOS

Use CLOS appropriately.

Meta-language guidelines

Macros

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

EVAL-WHEN

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

Read-time evaluation

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

EVAL

You must not use EVAL at runtime.

INTERN and UNINTERN

You must not use INTERN or UNINTERN at runtime.

Data Representation

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

Appropriately use or avoid using NIL.

Do not abuse lists

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

Lists vs. structures vs. multiple values

You should use the appropriate representation for product types.

Lists vs. Pairs

Use the appropriate functions when manipulating lists.

Lists vs. Arrays

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

Lists vs. Sets

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

You must use proper defining forms for constant values.

Defining Functions

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

Conditional Expressions

Use the appropriate conditional form.

Identity, Equality and Comparisons

You should use the appropriate predicates when comparing objects.

Iteration

Use the appropriate form for iteration.

I/O

Use the appropriate I/O functions.

Optimization

Avoid Allocation

You should avoid unnecessary allocation of memory.

Unsafe Operations

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

DYNAMIC-EXTENT

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

REDUCE vs APPLY

You should use REDUCE instead of APPLY where appropriate.

Avoid NCONC

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

Pitfalls

#'FUN vs. 'FUN

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

Pathnames

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

SATISFIES

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