# R Tip: Use seqi() For Indexes

`R` Tip: use `seqi()` for indexing.

`R`‘s `1:0` trap” is a mal-feature that confuses newcomers and is a reliable source of bugs. This note will show how to use `seqi()` to write more reliable code and document intent.

The issue is, contrary to expectations (formed in working with other programming languages) the sequence `1:0` is not empty. It is instead a decreasing sequence. Data scientists typically work in many languages, so we should expect differences. However having a sequence builder that returns empty when the bounds cross is a common useful tool for controlling loops and other indexing tasks.

We have written about this before. The usual defense is that it is the same as `seq(1, 0)`, but I see that more as a doubling-down than an argument. Also due to odd behavior when iterating over vectors or lists with class-attributes, we sometimes must introduce indices (as it isn’t always safe to directly iterate over contents in `R`).

What this means is in `R` there is no common safe, succinct way to write index vector or loops where one of the end-points is passed in as an argument. For example the following simple example is incorrect.

```# sum reciprocals of squares of positive integers from 1 up to k
# converges to pi^2/6
sum_sq_recip_k <- function(k) {
sum(1/((1:k)^2))
}

# should be zero, as the convention 1 up to -1 is the empty set
sum_sq_recip_k(-1)
#  Inf
```

There are plenty of ways to write reversed sequences (such as `rev(0:1)`), so writing reversed sequences isn’t a great unmet need. Previously we recommended using `seq_len()` as a solution. This is still good, however that only directly addressed upper-bound issues. For general ranges (where perhaps the lower-bound is the parameter) we still have a problem.

`Python` is one of the most popular programming languages, and it supplies a convenient function for the common task of iterating over increasing ranges of integers.

```# Python code

[k for k in range(3, 5)]
# Out: [3, 4]

[k for k in range(5, 3)]
# Out: []
```

Now of course different programming languages made different choices. However, in my opinion, writing possibly empty sequences parametrically is a common programming need and it is nice to have this be convenient.

Our current advice to `R` users is use `wrapr::seqi()` which stands for “sequence, increasing integer(s)”. We needed such a capability when translating `C++` code to `R` code for our `RcppDynProg` example (otherwise we would have to put guards around the loops so they don’t activate on what should be empty sequences).

`seqi()` is used as follows.

```library("wrapr")

# print 3, 4, and then 5
for(i in seqi(3, 5)) {
print(i)
}
#>  3
#>  4
#>  5

# empty
for(i in seqi(5, 2)) {
print(i)
}
```

This is clear, safe, and documents intent. It is a non-negotiable fact that in `R` `base::seq(1,0)` is `[0, 1]`. Well, `wrapr::seqi(1,0)` is `[]`.

Tags: