mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Google Common Lisp Style Guide updated to 1.13.
This commit is contained in:
parent
f981c5c266
commit
13bb6e417a
378
lispguide.xml
378
lispguide.xml
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<p align="right">
|
<p align="right">
|
||||||
|
|
||||||
Revision 1.12
|
Revision 1.13
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,8 +46,27 @@ Robert Brown
|
||||||
<p>
|
<p>
|
||||||
Common Lisp is a powerful multiparadigm programming language.
|
Common Lisp is a powerful multiparadigm programming language.
|
||||||
With great power comes great responsibility.
|
With great power comes great responsibility.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
This guide recommends formatting and stylistic choices
|
This guide recommends formatting and stylistic choices
|
||||||
designed to make your code easier for other people to understand.
|
designed to make your code easier for other people to understand.
|
||||||
|
Its guidelines apply to all the Common Lisp code we write at Google,
|
||||||
|
including our internal applications as well as
|
||||||
|
free software libraries we maintain and publish.
|
||||||
|
If you contribute to this code base,
|
||||||
|
you must follow these guidelines before you submit your patch,
|
||||||
|
or your code will be fixed to follow the guidelines after you do.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you're writing Common Lisp code outside Google,
|
||||||
|
we invite you to consider the guidelines we expound in this guide.
|
||||||
|
You may apply some or all of them to your own projects, at your leisure.
|
||||||
|
If you do, we hope that you will find some of them useful.
|
||||||
|
Even if you don't, we also welcome any remarks or constructive feedback
|
||||||
|
you may have on how to improve our guide, and
|
||||||
|
about what alternate styles are available.
|
||||||
|
Finally, we hope that our discussions will be thought-inspiring
|
||||||
|
to hackers who read them, especially so to newcomers to Common Lisp.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -141,8 +160,9 @@ Robert Brown
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
Permission comes from the OWNERS of your project.
|
Permission comes from the owners of your project.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Forgiveness is requested in a comment
|
Forgiveness is requested in a comment
|
||||||
near the point of guideline violation,
|
near the point of guideline violation,
|
||||||
|
@ -168,7 +188,16 @@ Robert Brown
|
||||||
Whatever the case may be, you must still follow these guidelines,
|
Whatever the case may be, you must still follow these guidelines,
|
||||||
as well as other conventional guidelines
|
as well as other conventional guidelines
|
||||||
that have not been formalized in this document.
|
that have not been formalized in this document.
|
||||||
You MUST follow conventions, because they are important for readability.
|
</p>
|
||||||
|
<p>
|
||||||
|
You MUST follow conventions.
|
||||||
|
They are important for readability.
|
||||||
|
When conventions are followed by default,
|
||||||
|
violations of the convention are a signal
|
||||||
|
that something notable is happening and deserves attention.
|
||||||
|
When conventions are systematically violated,
|
||||||
|
violations of the convention are a distracting noise
|
||||||
|
that needs to be ignored.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Conventional guidelines <em>are</em> indoctrination.
|
Conventional guidelines <em>are</em> indoctrination.
|
||||||
|
@ -451,7 +480,7 @@ Robert Brown
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
Use your judgement to distinguish
|
Use your judgment to distinguish
|
||||||
general-purpose versus business-specific code,
|
general-purpose versus business-specific code,
|
||||||
and open-source the general-purpose parts,
|
and open-source the general-purpose parts,
|
||||||
while keeping the business-specific parts a trade secret.
|
while keeping the business-specific parts a trade secret.
|
||||||
|
@ -630,8 +659,10 @@ Robert Brown
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
Some line length restriction is better than none at all.
|
Some line length restriction is better than none at all.
|
||||||
Allowing 100 columns seems better, since good style encourages
|
While old text terminals used to make 80 columns the standard,
|
||||||
the use of descriptive variables and function names.
|
these days, allowing 100 columns seems better,
|
||||||
|
since good style encourages the use of
|
||||||
|
descriptive variables and function names.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -890,25 +921,31 @@ Robert Brown
|
||||||
<CATEGORY title="Documentation">
|
<CATEGORY title="Documentation">
|
||||||
<STYLEPOINT title="Document everything">
|
<STYLEPOINT title="Document everything">
|
||||||
<SUMMARY>
|
<SUMMARY>
|
||||||
You should use document strings to explain how to use your code.
|
You should use document strings on all visible functions
|
||||||
|
to explain how to use your code.
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
You must comment anything complicated
|
Unless some bit of code is painfully self-explanatory,
|
||||||
so that the next developer can understand what's going on.
|
document it with a documentation string (also known as docstring).
|
||||||
(Again, the "hit by a truck" principle.)
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Unless some bit of code is painfully self-explanatory, document it.
|
Documentation strings are destined to be read
|
||||||
Prefer documentation strings to comments
|
by the programmers who use your code.
|
||||||
because the former can be displayed by programming tools, such as IDEs,
|
They can be extracted from functions, types, classes, variables and macros,
|
||||||
|
and displayed by programming tools, such as IDEs,
|
||||||
or by REPL queries such as <code>(describe 'foo)</code>;
|
or by REPL queries such as <code>(describe 'foo)</code>;
|
||||||
they can also be extracted
|
web-based documentation or other reference works
|
||||||
to create web-based documentation or other reference works.
|
can be created based on them.
|
||||||
|
Documentation strings are thus the perfect locus to document your API.
|
||||||
|
They should describe how to use the code
|
||||||
|
(including what pitfalls to avoid),
|
||||||
|
as opposed to how the code works (and where more work is needed),
|
||||||
|
which is what you'll put in comments.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Supply a documentation string (also known as docstring) when defining
|
Supply a documentation string when defining
|
||||||
top-level functions, types, classes, and macros.
|
top-level functions, types, classes, variables and macros.
|
||||||
Generally, add a documentation string wherever the language allows.
|
Generally, add a documentation string wherever the language allows.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -934,9 +971,7 @@ Robert Brown
|
||||||
nil)
|
nil)
|
||||||
(t
|
(t
|
||||||
(loop for i from 3 upto (sqrt n) by 2
|
(loop for i from 3 upto (sqrt n) by 2
|
||||||
do (when (divisorp i n)
|
never (divisorp i n)))))
|
||||||
(return-from small-prime-number-p nil)))
|
|
||||||
t)))
|
|
||||||
</CODE_SNIPPET>
|
</CODE_SNIPPET>
|
||||||
<CODE_SNIPPET>
|
<CODE_SNIPPET>
|
||||||
(defgeneric table-clear (table)
|
(defgeneric table-clear (table)
|
||||||
|
@ -982,6 +1017,28 @@ Robert Brown
|
||||||
You must use the appropriate number of semicolons to introduce comments.
|
You must use the appropriate number of semicolons to introduce comments.
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
|
<p>
|
||||||
|
Comments are explanations to the future maintainers of the code.
|
||||||
|
Even if you're the only person who will ever see and touch the code,
|
||||||
|
even if you're either immortal and never going to quit,
|
||||||
|
or unconcerned with what happens after you leave
|
||||||
|
(and have your code self-destruct in such an eventuality),
|
||||||
|
you may find it useful to comment your code.
|
||||||
|
Indeed, by the time you revisit your code,
|
||||||
|
weeks, months or years later,
|
||||||
|
you will find yourself a different person from the one who wrote it,
|
||||||
|
and you will be grateful to that previous self
|
||||||
|
for making the code readable.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You must comment anything complicated
|
||||||
|
so that the next developer can understand what's going on.
|
||||||
|
(Again, the "hit by a truck" principle.)
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Also use comments as a way to guide those who read the code,
|
||||||
|
so they know what to find where.
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
File headers and important comments
|
File headers and important comments
|
||||||
|
@ -1031,14 +1088,12 @@ Robert Brown
|
||||||
nil)
|
nil)
|
||||||
((= n 2) ; parenthetical remark here
|
((= n 2) ; parenthetical remark here
|
||||||
t) ; continuation of the remark
|
t) ; continuation of the remark
|
||||||
((divisible-by n 2)
|
((divisorp 2 n)
|
||||||
nil) ; different remark
|
nil) ; different remark
|
||||||
;; Comment that applies to a section of code.
|
;; Comment that applies to a section of code.
|
||||||
(t
|
(t
|
||||||
(loop for i from 3 upto (sqrt n) by 2
|
(loop for i from 3 upto (sqrt n) by 2
|
||||||
do (when (divisorp i n)
|
never (divisorp i n)))))
|
||||||
(return-from small-prime-number-p nil)))
|
|
||||||
t)))
|
|
||||||
</CODE_SNIPPET>
|
</CODE_SNIPPET>
|
||||||
<p>
|
<p>
|
||||||
You should include a space between the semicolon and the text of the comment.
|
You should include a space between the semicolon and the text of the comment.
|
||||||
|
@ -1564,7 +1619,7 @@ Robert Brown
|
||||||
</STYLEPOINT>
|
</STYLEPOINT>
|
||||||
<STYLEPOINT title="Recursion">
|
<STYLEPOINT title="Recursion">
|
||||||
<SUMMARY>
|
<SUMMARY>
|
||||||
Favor iteration over recursion.
|
You should favor iteration over recursion.
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
|
@ -1620,6 +1675,27 @@ Robert Brown
|
||||||
and only in cases where it won't surprise the person reading the code,
|
and only in cases where it won't surprise the person reading the code,
|
||||||
and where it offers significant benefits.
|
and where it offers significant benefits.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Indeed, each special variable constitutes state.
|
||||||
|
Developers have to mentally track the state of all relevant variables
|
||||||
|
when trying to understand what the code does and how it does it;
|
||||||
|
tests have to be written and run with all relevant combinations;
|
||||||
|
to isolate some activity, care has to be taken to locally bind
|
||||||
|
all relevant variables, including those of indirectly used modules.
|
||||||
|
They can hide precious information from being printed in a backtrace.
|
||||||
|
Not only is there overhead associated to each new variable,
|
||||||
|
but interactions between variables
|
||||||
|
can make the code exponentially more complex
|
||||||
|
as the number of such variables increases.
|
||||||
|
The benefits have to match the costs.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note though that a Lisp special variable is not a global variable
|
||||||
|
in the sense of a global variable in, say, BASIC or C.
|
||||||
|
As special variables can be dynamically bound to a local value,
|
||||||
|
they are much more powerful than
|
||||||
|
global value cells where all users necessarily interfere with each other.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Good candidates for such special variables
|
Good candidates for such special variables
|
||||||
are items for which "the current" can be naturally used as prefix,
|
are items for which "the current" can be naturally used as prefix,
|
||||||
|
@ -1640,22 +1716,20 @@ Robert Brown
|
||||||
that these functions also have this argument,
|
that these functions also have this argument,
|
||||||
which clutters the code with boilerplate.
|
which clutters the code with boilerplate.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
Note that a Lisp special variable is not a global variable
|
|
||||||
in the sense of a global variable in, say, BASIC or C.
|
|
||||||
As special variables can be dynamically bound to a local value,
|
|
||||||
they are much more powerful than
|
|
||||||
global value cells where users all interfere with each other.
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
You should treat special variables
|
You should treat special variables
|
||||||
as though they are per-thread variables.
|
as though they are per-thread variables.
|
||||||
That is, leave the special variable with no top-level binding at all,
|
By default, you should leave a special variable
|
||||||
|
with no top-level binding at all,
|
||||||
and each thread of control
|
and each thread of control
|
||||||
that needs the variable should bind it explicitly.
|
that needs the variable should bind it explicitly.
|
||||||
This will mean that any incorrect use of the variable
|
This will mean that any incorrect use of the variable
|
||||||
will result in an "unbound variable" error, and
|
will result in an "unbound variable" error, and
|
||||||
each thread will see its own value for the variable.
|
each thread will see its own value for the variable.
|
||||||
|
Variables with a default global value should usually be
|
||||||
|
locally bound at thread creation time.
|
||||||
|
You should use suitable infrastructure
|
||||||
|
to automate the appropriate declaration of such variables.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -1817,7 +1891,7 @@ Robert Brown
|
||||||
Code should not signal conditions from inside the cleanup form of
|
Code should not signal conditions from inside the cleanup form of
|
||||||
<code>UNWIND-PROTECT</code>
|
<code>UNWIND-PROTECT</code>
|
||||||
(unless they are always handled inside the cleanup form),
|
(unless they are always handled inside the cleanup form),
|
||||||
or otherwise do non-local exits from cleanup handers
|
or otherwise do non-local exits from cleanup handlers
|
||||||
outside of the handler e.g. <code>INVOKE-RESTART</code>.
|
outside of the handler e.g. <code>INVOKE-RESTART</code>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -2015,7 +2089,15 @@ Robert Brown
|
||||||
which might be a symbol or something.
|
which might be a symbol or something.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You must not use MOP "intercessory" operations.
|
You must not use MOP "intercessory" operations at runtime.
|
||||||
|
You should not use MOP "intercessory" operations at compile-time.
|
||||||
|
At runtime, they are at worst a danger, at best a performance issue.
|
||||||
|
At compile-time, it is usually cleaner that
|
||||||
|
macros should things up the right way on the first pass,
|
||||||
|
without the need to modify things in a second pass.
|
||||||
|
MOP intercession is a great tool for interactive development,
|
||||||
|
and you may enjoy it while debugging;
|
||||||
|
but you should not use it in normal applications.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If a class definition creates a method
|
If a class definition creates a method
|
||||||
|
@ -2238,7 +2320,7 @@ Robert Brown
|
||||||
that generates code to do this.
|
that generates code to do this.
|
||||||
See also <code>ALEXANDRIA:WITH-GENSYMS</code>,
|
See also <code>ALEXANDRIA:WITH-GENSYMS</code>,
|
||||||
to make some temporary variables in the generated code.
|
to make some temporary variables in the generated code.
|
||||||
Note that if you follow our <code>CALL-WITH-</code> style,
|
Note that if you follow our <code>CALL-WITH</code> style,
|
||||||
you typically expand the code only once, as either
|
you typically expand the code only once, as either
|
||||||
an argument to the auxiliary function, or
|
an argument to the auxiliary function, or
|
||||||
the body of a lambda passed as argument to it;
|
the body of a lambda passed as argument to it;
|
||||||
|
@ -2450,12 +2532,55 @@ Robert Brown
|
||||||
</p>
|
</p>
|
||||||
</BODY>
|
</BODY>
|
||||||
</STYLEPOINT>
|
</STYLEPOINT>
|
||||||
|
<STYLEPOINT title="INTERN and UNINTERN">
|
||||||
|
<SUMMARY>
|
||||||
|
You must not use <code>INTERN</code> or <code>UNINTERN</code> at runtime.
|
||||||
|
</SUMMARY>
|
||||||
|
<BODY>
|
||||||
|
<p>
|
||||||
|
You must not use <code>INTERN</code> at runtime.
|
||||||
|
Not only does it cons,
|
||||||
|
it either creates a permanent symbol that won't be collected
|
||||||
|
or gives access to internal symbols.
|
||||||
|
This creates opportunities for memory leaks, denial of service attacks,
|
||||||
|
unauthorized access to internals, clashes with other symbols.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You must not <code>INTERN</code> a string
|
||||||
|
just to compare it to a keyword;
|
||||||
|
use <code>STRING=</code> or <code>STRING-EQUAL</code>.
|
||||||
|
</p>
|
||||||
|
<BAD_CODE_SNIPPET>
|
||||||
|
(member (intern str :keyword) $keys) ; Bad
|
||||||
|
</BAD_CODE_SNIPPET>
|
||||||
|
<CODE_SNIPPET>
|
||||||
|
(member str $keys :test #'string-equal) ; Better
|
||||||
|
</CODE_SNIPPET>
|
||||||
|
<p>
|
||||||
|
You must not use <code>UNINTERN</code> at runtime.
|
||||||
|
It can break code that relies on dynamic binding.
|
||||||
|
It makes things harder to debug.
|
||||||
|
You must not dynamically intern any new symbol,
|
||||||
|
and therefore you need not dynamically unintern anything.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You may of course use <code>INTERN</code> at compile-time,
|
||||||
|
in the implementation of some macros.
|
||||||
|
Even so, it is usually more appropriate
|
||||||
|
to use abstractions on top of it, such as
|
||||||
|
<code>ALEXANDRIA:SYMBOLICATE</code> or
|
||||||
|
<code>ALEXANDRIA:FORMAT-SYMBOL</code>
|
||||||
|
to create the symbols you need.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</BODY>
|
||||||
|
</STYLEPOINT>
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
<CATEGORY title="Data Representation">
|
<CATEGORY title="Data Representation">
|
||||||
<STYLEPOINT title="NIL: empty-list, false and I Don't Know">
|
<STYLEPOINT title="NIL: empty-list, false and I Don't Know">
|
||||||
<SUMMARY>
|
<SUMMARY>
|
||||||
Appropriately use or avoid to use <code>NIL</code>.
|
Appropriately use or avoid using <code>NIL</code>.
|
||||||
</SUMMARY>
|
</SUMMARY>
|
||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
|
@ -2699,67 +2824,6 @@ Robert Brown
|
||||||
</p>
|
</p>
|
||||||
</BODY>
|
</BODY>
|
||||||
</STYLEPOINT>
|
</STYLEPOINT>
|
||||||
<STYLEPOINT title="#'FUN vs. 'FUN">
|
|
||||||
<SUMMARY>
|
|
||||||
You should usually refer to a function as <code>#'FOO</code> rather than <code>'FOO</code>.
|
|
||||||
</SUMMARY>
|
|
||||||
<BODY>
|
|
||||||
<p>
|
|
||||||
The former, which reads as <code>(FUNCTION FOO)</code>,
|
|
||||||
refers to the function object, and is properly scoped.
|
|
||||||
The latter, which reads as <code>(QUOTE FOO)</code>,
|
|
||||||
refers to the symbol, which when called
|
|
||||||
uses the global <code>FDEFINITION</code> of the symbol.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
When using functions that take a functional argument
|
|
||||||
(e.g., <code>MAPCAR</code>, <code>APPLY</code>,
|
|
||||||
<code>:TEST</code> and <code>:KEY</code> arguments),
|
|
||||||
you should use the <code>#'</code> to quote the function,
|
|
||||||
not just single quote.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
An exception is when you explicitly want dynamic linking,
|
|
||||||
because you anticipate that
|
|
||||||
the global function binding will be updated.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Another exception is when you explicitly want to access
|
|
||||||
a global function binding,
|
|
||||||
and avoid a possible shadowing lexical binding.
|
|
||||||
This shouldn't happen often, as it is usually a bad idea
|
|
||||||
to shadow a function when you will want to use the shadowed function;
|
|
||||||
just use a different name for the lexical function.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You must consistently use either <code>#'(lambda ...)</code>
|
|
||||||
or <code>(lambda ...)</code> without <code>#'</code> everywhere.
|
|
||||||
Unlike the case of <code>#'symbol</code> vs <code>'symbol</code>,
|
|
||||||
it is only a syntactic difference with no semantic impact,
|
|
||||||
except that the former works on Genera and the latter doesn't.
|
|
||||||
You must use the former style if your code is intended as a library
|
|
||||||
with maximal compatibility to all Common Lisp implementations;
|
|
||||||
otherwise, it is optional which style you use.
|
|
||||||
<code>#'</code> may be seen as a hint
|
|
||||||
that you're introducing a function in expression context;
|
|
||||||
but the <code>lambda</code> itself is usually sufficient hint,
|
|
||||||
and concision is good.
|
|
||||||
Choose wisely, but above all,
|
|
||||||
consistently with yourself and other developers,
|
|
||||||
within a same file, package, system, project, etc.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Note that if you start writing a new system
|
|
||||||
in a heavily functional style,
|
|
||||||
you may consider using
|
|
||||||
<a href="http://cliki.net/lambda-reader">lambda-reader</a>,
|
|
||||||
a system that lets you use the unicode character <code>λ</code>
|
|
||||||
instead of <code>LAMBDA</code>.
|
|
||||||
But you must not start using such a syntactic extension
|
|
||||||
in an existing system without getting permission from other developers.
|
|
||||||
</p>
|
|
||||||
</BODY>
|
|
||||||
</STYLEPOINT>
|
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
<CATEGORY title="Proper Forms">
|
<CATEGORY title="Proper Forms">
|
||||||
|
@ -2923,11 +2987,21 @@ Robert Brown
|
||||||
<p>
|
<p>
|
||||||
Note that in Common Lisp,
|
Note that in Common Lisp,
|
||||||
<code>WHEN</code> and <code>UNLESS</code> return <code>NIL</code>
|
<code>WHEN</code> and <code>UNLESS</code> return <code>NIL</code>
|
||||||
when the condition evaluates to <code>NIL</code>.
|
when the condition is not met.
|
||||||
|
You may take advantage of it.
|
||||||
Nevertheless, you may use an <code>IF</code>
|
Nevertheless, you may use an <code>IF</code>
|
||||||
to explicitly return <code>NIL</code>
|
to explicitly return <code>NIL</code>
|
||||||
if you have a specific reason to insist on the return value.
|
if you have a specific reason to insist on the return value.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
You should include a fall-through clause <code>(t nil)</code>
|
||||||
|
as the last in your <cond>COND</cond>,
|
||||||
|
or <code>(otherwise nil)</code> as the last in your <cond>CASE</cond>
|
||||||
|
when the value returned by the conditional matters
|
||||||
|
and such a case is going to be used.
|
||||||
|
You should omit the fall-through clause
|
||||||
|
when the conditional is used for side-effects.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You should prefer <code>AND</code> and <code>OR</code>
|
You should prefer <code>AND</code> and <code>OR</code>
|
||||||
when it leads to more concise code than using
|
when it leads to more concise code than using
|
||||||
|
@ -3232,49 +3306,6 @@ Robert Brown
|
||||||
</dl>
|
</dl>
|
||||||
</BODY>
|
</BODY>
|
||||||
</STYLEPOINT>
|
</STYLEPOINT>
|
||||||
<STYLEPOINT title="INTERN and UNINTERN">
|
|
||||||
<SUMMARY>
|
|
||||||
You must not use <code>INTERN</code> or <code>UNINTERN</code> at runtime.
|
|
||||||
</SUMMARY>
|
|
||||||
<BODY>
|
|
||||||
<p>
|
|
||||||
You must not use <code>INTERN</code> it at runtime.
|
|
||||||
Not only does it cons,
|
|
||||||
it either creates a permanent symbol that won't be collected
|
|
||||||
or gives access to internal symbols.
|
|
||||||
This creates opportunities for memory leaks, denial of service attacks,
|
|
||||||
unauthorized access to internals, clashes with other symbols.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You must not <code>INTERN</code> a string
|
|
||||||
just to compare it to a keyword;
|
|
||||||
use <code>STRING=</code> or <code>STRING-EQUAL</code>.
|
|
||||||
</p>
|
|
||||||
<BAD_CODE_SNIPPET>
|
|
||||||
(member (intern str :keyword) $keys) ; Bad
|
|
||||||
</BAD_CODE_SNIPPET>
|
|
||||||
<CODE_SNIPPET>
|
|
||||||
(member str $keys :test #'string-equal) ; Better
|
|
||||||
</CODE_SNIPPET>
|
|
||||||
<p>
|
|
||||||
You must not use <code>UNINTERN</code> at runtime.
|
|
||||||
It can break code that relies on dynamic binding.
|
|
||||||
It makes things harder to debug.
|
|
||||||
You must not dynamically intern any new symbol,
|
|
||||||
and therefore you need not dynamically unintern anything.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You may of course use <code>INTERN</code> at compile-time,
|
|
||||||
in the implementation of some macros.
|
|
||||||
Even so, it is usually more appropriate
|
|
||||||
to use abstractions on top of it, such as
|
|
||||||
<code>ALEXANDRIA:SYMBOLICATE</code> or
|
|
||||||
<code>ALEXANDRIA:FORMAT-SYMBOL</code>
|
|
||||||
to create the symbols you need.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</STYLEPOINT>
|
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
<CATEGORY title="Optimization">
|
<CATEGORY title="Optimization">
|
||||||
|
@ -3590,6 +3621,67 @@ Robert Brown
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
<CATEGORY title="Pitfalls">
|
<CATEGORY title="Pitfalls">
|
||||||
|
<STYLEPOINT title="#'FUN vs. 'FUN">
|
||||||
|
<SUMMARY>
|
||||||
|
You should usually refer to a function as <code>#'FOO</code> rather than <code>'FOO</code>.
|
||||||
|
</SUMMARY>
|
||||||
|
<BODY>
|
||||||
|
<p>
|
||||||
|
The former, which reads as <code>(FUNCTION FOO)</code>,
|
||||||
|
refers to the function object, and is properly scoped.
|
||||||
|
The latter, which reads as <code>(QUOTE FOO)</code>,
|
||||||
|
refers to the symbol, which when called
|
||||||
|
uses the global <code>FDEFINITION</code> of the symbol.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When using functions that take a functional argument
|
||||||
|
(e.g., <code>MAPCAR</code>, <code>APPLY</code>,
|
||||||
|
<code>:TEST</code> and <code>:KEY</code> arguments),
|
||||||
|
you should use the <code>#'</code> to quote the function,
|
||||||
|
not just single quote.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
An exception is when you explicitly want dynamic linking,
|
||||||
|
because you anticipate that
|
||||||
|
the global function binding will be updated.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Another exception is when you explicitly want to access
|
||||||
|
a global function binding,
|
||||||
|
and avoid a possible shadowing lexical binding.
|
||||||
|
This shouldn't happen often, as it is usually a bad idea
|
||||||
|
to shadow a function when you will want to use the shadowed function;
|
||||||
|
just use a different name for the lexical function.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You must consistently use either <code>#'(lambda ...)</code>
|
||||||
|
or <code>(lambda ...)</code> without <code>#'</code> everywhere.
|
||||||
|
Unlike the case of <code>#'symbol</code> vs <code>'symbol</code>,
|
||||||
|
it is only a syntactic difference with no semantic impact,
|
||||||
|
except that the former works on Genera and the latter doesn't.
|
||||||
|
You must use the former style if your code is intended as a library
|
||||||
|
with maximal compatibility to all Common Lisp implementations;
|
||||||
|
otherwise, it is optional which style you use.
|
||||||
|
<code>#'</code> may be seen as a hint
|
||||||
|
that you're introducing a function in expression context;
|
||||||
|
but the <code>lambda</code> itself is usually sufficient hint,
|
||||||
|
and concision is good.
|
||||||
|
Choose wisely, but above all,
|
||||||
|
consistently with yourself and other developers,
|
||||||
|
within a same file, package, system, project, etc.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that if you start writing a new system
|
||||||
|
in a heavily functional style,
|
||||||
|
you may consider using
|
||||||
|
<a href="http://cliki.net/lambda-reader">lambda-reader</a>,
|
||||||
|
a system that lets you use the unicode character <code>λ</code>
|
||||||
|
instead of <code>LAMBDA</code>.
|
||||||
|
But you must not start using such a syntactic extension
|
||||||
|
in an existing system without getting permission from other developers.
|
||||||
|
</p>
|
||||||
|
</BODY>
|
||||||
|
</STYLEPOINT>
|
||||||
<STYLEPOINT title="Pathnames">
|
<STYLEPOINT title="Pathnames">
|
||||||
<SUMMARY>
|
<SUMMARY>
|
||||||
Common Lisp pathnames are tricky. Be aware of pitfalls.
|
Common Lisp pathnames are tricky. Be aware of pitfalls.
|
||||||
|
@ -3780,7 +3872,7 @@ Robert Brown
|
||||||
</small>
|
</small>
|
||||||
|
|
||||||
<p align="right">
|
<p align="right">
|
||||||
Revision 1.12
|
Revision 1.13
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user