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 Meta-Guide Must, Should, May, or Not Permission and Forgiveness Conventions Old Code Future Topics General Guidelines Principles Priorities Architecture Using Libraries Open-Sourcing Code Development Process Formatting Spelling and Abbreviations Line length Indentation File Header Vertical white space Horizontal white space Documentation Document everything Comment semicolons Grammar and punctuation Attention Required Domain-Specific Languages Naming Symbol guidelines Denote intent, not content Global variables and constants Predicate names Omit library prefixes Packages Language usage guidelines Mostly Functional Style Recursion Special variables Assignment Assertions and Conditions Type Checking CLOS Meta-language guidelines Macros EVAL-WHEN Read-time evaluation EVAL INTERN and UNINTERN Data Representation NIL: empty-list, false and I Don't Know Do not abuse lists Lists vs. structures vs. multiple values Lists vs. Pairs Lists vs. Arrays Lists vs. Sets Proper Forms Defining Constants Defining Functions Conditional Expressions Identity, Equality and Comparisons Iteration I/O Optimization Avoid Allocation Unsafe Operations DYNAMIC-EXTENT REDUCE vs APPLY Avoid NCONC Pitfalls #'FUN vs. 'FUN Pathnames SATISFIES 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