Another R tip. Use `seq_len()`

to avoid the backwards sequence trap.

Many R users use the “colon sequence” notation to build sequences. For example:

for(i in 1:5) { print(paste(i, i*i)) } #> [1] "1 1" #> [1] "2 4" #> [1] "3 9" #> [1] "4 16" #> [1] "5 25"

However, the colon notation can be unsafe as it does not properly handle the empty sequence case:

n <- 0 1:n #> [1] 1 0

Notice the above example built a reversed sequence, instead of an empty sequence.

This leads to the backwards sequence trap: writing code of the form “`1:length(x)`

” is often wrong. For example “`for(i in 1:length(x)) { statements involving x[[i]] }`

“, which will fail for length-zero `x`

.

To avoid this use `seq_len()`

or `seq_along()`

:

seq_len(5) #> [1] 1 2 3 4 5 n <- 0 seq_len(n) #> integer(0)

“`integer(0)`

” is a length zero sequence of integers (not a sequence containing the value zero).

### jmount

Data Scientist and trainer at Win Vector LLC. One of the authors of Practical Data Science with R.

I may be missing something, but I don’t understand why you call the result of 1:0 a bug. That produces exactly what I would expect it to.

The “:” operator can be thought of as shorthand for a call to the seq() function. This shorthand only accepts 2 of the arguments that seq() accepts—“from” and “to”—default values are used for the others. Note that seq(1,0) returns the same result that 1:0 does. To get an empty string, just issue seq(length.out=0).

Two R results that I mentioned:

LikeLike

Thanks for your comment. I left a bit out which I have now put at the end of the article with an edit. Sorry about that.

The behavior does match

`help(`:`)`

, so it isn’t a bug on its own. But it is a key part of buggy for-loops such as this:From https://www.r-bloggers.com/writing-a-for-loop-in-r/:

The above errors out if

`foo`

has length 0. And the above form is unfortunately taught a lot. The fix I suggest is use`seq_len()`

. Yes, one can use`vapply()`

in this case.I wish I had said it in the original article, but code of the form

`1:length(x)`

is a very common (so common I forgot I had not mentioned it), and this the use of “`:`

” and is often wrong (not what the programmer actually intended).LikeLike

Agree that bug in the headline is misleading. Maybe replace “bug” with “situation”.

LikeLike

Thanks! That is the idea that was not coming to me. I am going to say “trap” (still strong, but less misleading).

LikeLike

That sounds good to me! Thanks for your articles.

LikeLike

for(i in 1:5) {

+ print(paste(i, i*i))

+ }

produces-

[1] “1 1”

[1] “2 4”

[1] “3 9”

[1] “4 16”

[1] “5 25”

omitting the last line makes me worry that you wrote this in python ðŸ™‚

LikeLike

Thank you. And sorry about that (now fixed).

And that is why I should have used RMarkdown instead of copying and pasting!

LikeLike

Turns out we are all in good company:

(Quoted from the fortunes package.)

LikeLike