Layout and Comments
Layout
Basic indentation should be 2.
for (ii in seq(nElements))
a[ii] <- 0;
Indentation of 1 is too small to emphasize the logical layout of the code. Indentation larger than 4 makes deeply nested code difficult to read and increase the chance that the lines must be split. Choosing between indentation of 2, 3 and 4, 2 and 4 are the more common, and 2 is chosen to reduce the risk of having to wrap code lines.
Block layout should be as illustrated in example 1 below or example 2, and must not be as shown in example 3. Class, Interface and method blocks should use the block layout of example 2.
while (!isDone) {
doSomething();
isDone <- moreToDo();
}
while (!isDone)
{
doSomething();
isDone <- moreToDo();
}
while (!isDone)
{
doSomething();
isDone <- moreToDo();
}
Example 1 and Example 2 are commonly used and some prefer the former whereas some the latter. Since it is more or less "impossible" to agree to use only one of these, both are recommended. In addition of being a matter of taste, both have there pros and cons.
Example 3 introduce an extra indentation level which doesn't emphasize the logical structure of the code as clearly as example 1 and 2.
S3 method declarations should have the following form:
someMethod.SomeClass <- function(object) {
...
}
The if-else class of statements should have the following form:
if (condition) {
statements;
}
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else {
statements;
}
This follows partly from the general block rule above. Note that the else clause have to be on the same line as the closing bracket of the previous if (or else) clause. If not, the previous if clause is considered to be finished at previous line. When the R parse then reaches the else statement on the next line it complains (with an "Error: syntax error" message), because a else must have start with an if statement. Thus, the following is syntactically erroneous in R:
# This is... # ...equivalent to this:
if (condition) { if (condition) {
statements; statements;
} };
else { else {
statements; statements;
} }
A for statement should have the following form:
for (variable in sequence) {
statements;
}
This follows from the general block rule above.
A while statement should have the following form:
while (condition) {
statements;
}
This follows from the general block rule above.
A switch statement should have the following form:
switch(condition,
"ABC" = {
statements;
},
"DEF" = {
statements;
},
"XYZ" = {
statements;
}
}
A tryCatch statement should have the following form:
tryCatch({
statements;
}, error = function(error) {
statements;
})
tryCatch({
statements;
}, error = function(error) {
statements;
}, finally = {
statements;
})
This follows partly from the general block rule above.
Single statement if-else, for or while statements can be written without brackets.
if (condition)
statement;
while (condition)
statement;
for (variable in sequence)
statement;
Use this only if the statement is short enough, and never use it when it spans multiple lines.
It is a common recommendation that brackets should always be used in all these cases. However, brackets are in general a language construct that groups several statements. Brackets are per definition superfluous on a single statement.
White Space
- Conventional operators should be surrounded by a space character.
- R reserved words should be followed by a white space.
- Commas should be followed by a white space.
- Colons should be surrounded by white space.
- Semicolons in for statements should be followed by a space character.
a <- (b + c) * d; # NOT: a<-(b+c)*d
while (TRUE) { # NOT: while(TRUE) ...
doSomething(a, b, c, d); # NOT: doSomething(a,b,c,d);
Makes the individual components of the statements stand out. Enhances readability. It is difficult to give a complete list of the suggested use of whitespace in R code. The examples above however should give a general idea of the intentions.
Logical units within a block should be separated by one blank line.
Enhances readability by introducing white space between logical units of a block.
Methods should be separated by 3-5 blank lines.
By making the space larger than space within a method, the methods will stand out within the class.
Statements should be aligned wherever this enhances readability.
value <- (potential * oilDensity) / constant1 +
(depth * waterDensity) / constant2 +
(zCoordinateValue * gasDensity) / constant3;
minPosition <- computeDistance(min, x, y, z);
averagePosition <- computeDistance(average, x, y, z);
# A function definition extending over multiple lines.
ll <- function(pattern=".*", ..., private=FALSE, properties="data.class",
sortBy=NULL, envir=parent.frame()) {
...
}
# Alternatively, right alignment may be used.
ll <- function(pattern=".*", ..., private=FALSE, properties="data.class",
sortBy=NULL, envir=parent.frame()) {
...
}
There are a number of places in the code where white space can be included to enhance readability even if this violates common guidelines. Many of these cases have to do with code alignment. General guidelines on code alignment are difficult to give, but the examples above should give some general hints. In short, any construction that enhances readability is allowed.
Comments
Tricky code should not be commented but rewritten. [2]
In general, the use of comments should be minimized by making the code self-documenting by appropriate name choices and an explicit logical structure.
All comments should be written in English.
In an international environment English is the preferred language.
Comments should be indented relative to their position in the code. [2]
while (TRUE) { # NOT: while (TRUE) {
# Do something # # Do something
something(); # something();
} # }
This is to avoid that the comments break the logical structure of the program.
Acknowledgments
I wish to thank (in alphabetic order) the following persons for valueable comments, sugestions, and improved guidelines:
Jan Kim, School of Computing Sciences, University of East Anglia, UK.
Gordon Smyth, Walter & Eliza Hall Institute of Medical Research, Australia.
Jason Turner, Inidigo Industrial Controls, New Zeeland.
References
[1] R Development Core Team, R Language Definition, ISBN 3-901167-56-0.
http://cran.r-project.org/manuals.html
[2] Java Code Conventions
http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html
[3] Java Programming Style Guidelines v3.0, Geotechnical Software Services
http://geosoft.no/javastyle.html
[4] R Development Core Team, Writing R Extensions, ISBN 3-901167-54-4.
http://cran.r-project.org/manuals.html
[5] Henrik Bengtsson, Safely creating S3 generic functions using setGenericS3(), Division for Mathematical Statistics, Centre for Mathematical Sciences, Lund University, Sweden, 2002.
http://www.maths.lth.se/help/R/