TRUE <- "Not TRUE anymore"
Error in TRUE <- "Not TRUE anymore": invalid (do_set) left-hand side to assignment
print(TRUE)
[1] TRUE
T
/F
Instead of TRUE
/FALSE
You are writing the abbreviated forms of TRUE
and FALSE
, T
and F
or you are using T
or F
as names.
Change the abbreviation to the full words or use a different variable name.
In R, T
and F
are variables being set to TRUE
and FALSE
, respectively. However, those variables can be redefined by the user since these are not reserved words as TRUE
and FALSE
are (see the R Language Definition for more details). This can result in unexpected code behavior as users of your package might have variables named T
/F
.
The first example shows that you cannot overwrite TRUE
:
TRUE <- "Not TRUE anymore"
Error in TRUE <- "Not TRUE anymore": invalid (do_set) left-hand side to assignment
print(TRUE)
[1] TRUE
This throws an error as TRUE
is a reserved word and the value of TRUE
does not change.
T
(and F
) on the other hand can be set to a different value:
<- "Not TRUE anymore"
T
print(T)
[1] "Not TRUE anymore"
To avoid any unexpected behaviors and inconsistencies, CRAN reviewers will ask you to write the reserved words, TRUE
and FALSE
instead of their abbreviated forms. For the same reason, T
or F
should not be used as variable names in your code, examples, tests or vignettes.
In your functions, you are setting a the random seed to a specific number which cannot be changed.
Remove the code that sets the seed. If you want to set it specifically in your functions, users should be able to set no seed if they want.
Changing the seed is not necessarily forbidden. However, users should be able to control which seed to use. Therefore, avoid code that changes the seed without user consent (e.g.: set.seed(123)
). A good solution for allowing to set a seed is to add an argument seed
to your function and set it conditionally.
function(... , seed = NULL){
if(!is.null(seed)){
set.seed(seed)
}
#the rest of your function can be written here.
}
This allows users to avoid setting a seed if they change the argument to NULL
. Ideally, the argument is already set to NULL
per default.
In your examples, vignettes, demos and tests setting a seed is not only allowed but also recommended to ensure reproducible results.
print()
/cat()
You are using functions, like print()
or cat()
, to print unsuppressable output to the console.
Change print()
/cat()
to message()
, warning()
, stop()
, or wrap them in if(verbose){}
.
Information messages, like loop counts or status updates, can clutter the console. While some users prefer this display, others appreciate less information on their console. The use of printing functions for console output is not forbidden on CRAN. However, this output must be suppressable by users.
Printing in special functions like print, summary, interactive functions or methods for generic functions is accepted.
To allow users to suppress the console output CRAN recommends two different ways:
cat()
/print()
with other generics
This allows to use functions like suppressMessages()
to avoid unwanted output.
verbose
, other names are acceptedThis example code shows the use of a verbose
argument to allow users to suppress printing
<- function(..., verbose = TRUE){
foo # your code
if(verbose){
print("Whatever you want to say!")
}# your code
}
Functions can print per default, like the example above, as long as the printing can be turned off (here, by setting verbose = FALSE
).
print()
and cat()
are not the only functions which can write output onto the console. The issue described in the recipe, also applies to the use of other printing function like writeLines()
. If you are using loggers to document your functions’ process, make sure that users can set their log level such that not messages are displayed.
You are changing the par()
, options()
or setwd()
in your functions, examples, demos or vignettes without resetting them.
Reset the changed options, in your functions by using on.exit()
or in examples, demos and vignettes with an additional line of code after the example.
Ideally, the user’s options are not changed at all. If they really have to be altered, restoring the previous values of user options is mandatory for CRAN packages. The reason for this rule is this line stated in the CRAN Repository Policy:
The code and examples provided in a package should never do anything which might be regarded as malicious or anti-social.
Resetting options is therefore mainly a Quality-of-Life feature for users of your package.
There are different ways of resetting for functions, and examples, demos or vignettes which are recommended by CRAN.
Changing par()
, options()
or setwd()
all invisibly return the previous values and therefore these can be stored in variables using the assignment operator <-
and later be restored by calling the variable name as argument in the respective function.
For functions:
When changing options inside one of your package functions, you can use on.exit()
for restoring.
<- function(x){
foo
# par():
<- par(mfrow = c(2,2))
oldpar on.exit(par(oldpar))
# options():
<- options(digits = 3)
oldop on.exit(options(oldop))
# setwd():
<- setwd(".")
oldwd on.exit(setwd(oldwd))
# your code which requires a changed option
}
This will reset the par()
, options()
and setwd()
. The use of on.exit()
makes it possible to restore options before exiting a function even if the function breaks. Therefore it needs to be called immediately after the option change within a function. For more information, call ?on.exit()
in your console.
For demos, examples and vignettes: Since no function is exited when changing options in examples, on.exit()
cannot be used. CRAN recommends the following way for restoring options:
<- par(mfrow = c(2,2))
oldpar
# your code which requires a changed option
par(oldpar)
Here the code will only reset the options if the example runs without breaking. Therefore, try to keep the code between setting and resetting as concise as possible. Restoring the options()
and setwd()
can be done using the same principle as for par()
shown above.
If you need to change more than one option in the same function, example, vignette or demo, you can use oldpar <- par(no.readonly = TRUE)
or oldop <- options()
to reset all parameters at once. Saving the entire Note, that for par()
the no.readonly
argument must be set to TRUE
or else warnings will be produced.
The issue described in the recipe, also applies to the use of other function which change some parameters persistently, like Sys.setLanguage
.