These are some of the use cases in which I explicitly use the L
suffix in declaring the constants. Of course these are not strictly "canonical" (or the only ones), but maybe you can have an idea of the rationale behind. I added, for each case, a "necessary" flag; you will see that these arise only if you interface other languages (like C).
- Logical type conversion (not necessary)
Instead of using a classic as.integer
, I use adding 0L
to a logical vector to make it integer. Of course you could just use 0
, but this would require more memory (typically 8 bytes instead of four) and a conversion.
- Manipulating the result of a function that returns integer (not necessary)
Say for instance that you want to find to retrieve the elements of the vector after a NA
. You could:
which(is.na(vec)) + 1L
Since which
returns an integer
, adding 1L
will preserve the type and avoid an implicit conversion. Nothing will happen if you omit the L
, since it's just a small optimization. This happens also with match
for instance: if you want to post-process the result of such a function, it's good habit to preserve the type if possible.
- Interfacing C (necessary)
From ?integer
:
Integer vectors exist so that data can be passed to C or Fortran
code which expects them, and so that (small) integer data can be
represented exactly and compactly.
C is much stricter regarding data types. This implies that, if you pass a vector to a C function, you can not rely on C to do the conversions. Say that you want to replace the elements after a NA with some value, say 42. You find the positions of the NA values at the R level (as we did before with which
) and then pass the original vector and the vector of indices to C. The C function will look like:
SEXP replaceAfterNA (SEXP X, SEXP IND) {
...
int *ind = INTEGER(IND);
...
for (i=0; i<l; i++) {
//make here the replacement
}
}
and the from the R side:
...
ind <- which(is.na(x)) + 1L
.Call("replaceAfterNA", x, ind)
...
If you omit the L
in the first line of above, you will receive an error like:
INTEGER() cannot be applied to double vectors
since C is expecting an integer type.
- Interfacing Java (necessary)
Same as before. If you use the rJava
package and want R to call your own custom Java classes and methods, you have to be sure that an integer is passed when the Java method requires an integer. Not adding a specific example here, but it should be clear why you may want to use the L
suffix in constants in these cases.
Addendum
The previous cases where about when you may want to use L
. Even if I guess much less common, it might be useful to add a case in which you don't want the L
. This may arise if there is danger of integer overflow. The *
, +
and -
operators preserve the type if both the operand are integer. For example:
#this overflows
31381938L*3231L
#[1] NA
#Warning message:
#In 31381938L * 3231L : NAs produced by integer overflow
#this not
31381938L*3231
#[1] 1.01395e+11
So, if you are doing operations on an integer variable which might produce overflow, it's important to cast it to double
to avoid any risk. Adding/subtracting to that variable a constant without the L
might be a good occasion as any to make the cast.