Require usage of startsWith()
and endsWith()
over grepl()
/substr()
versions
Source: R/string_boundary_linter.R
string_boundary_linter.Rd
startsWith()
is used to detect fixed initial substrings; it is more
readable and more efficient than equivalents using grepl()
or substr()
.
c.f. startsWith(x, "abc")
, grepl("^abc", x)
,
substr(x, 1L, 3L) == "abc"
.
Arguments
- allow_grepl
Logical, default
FALSE
. IfTRUE
, usages withgrepl()
are ignored. Some authors may prefer the conciseness offered bygrepl()
wherebyNA
input maps toFALSE
output, which doesn't have a direct equivalent withstartsWith()
orendsWith()
.
Details
Ditto for using endsWith()
to detect fixed terminal substrings.
Note that there is a difference in behavior between how grepl()
and startsWith()
(and endsWith()
) handle missing values. In particular, for grepl()
, NA
inputs
are considered FALSE
, while for startsWith()
, NA
inputs have NA
outputs.
That means the strict equivalent of grepl("^abc", x)
is
!is.na(x) & startsWith(x, "abc")
.
We lint grepl()
usages by default because the !is.na()
version is more explicit
with respect to NA
handling – though documented, the way grepl()
handles
missing inputs may be surprising to some users.
See also
linters for a complete list of linters available in lintr.
Examples
# will produce lints
lint(
text = 'grepl("^a", x)',
linters = string_boundary_linter()
)
#> <text>:1:7: warning: [string_boundary_linter] Use !is.na(x) & startsWith(x, string) to detect a fixed initial substring, or, if missingness is not a concern, just startsWith(). Doing so is more readable and more efficient.
#> grepl("^a", x)
#> ^~~~
lint(
text = 'grepl("z$", x)',
linters = string_boundary_linter()
)
#> <text>:1:7: warning: [string_boundary_linter] Use !is.na(x) & endsWith(x, string) to detect a fixed terminal substring, or, if missingness is not a concern, just endsWith(). Doing so is more readable and more efficient.
#> grepl("z$", x)
#> ^~~~
# okay
lint(
text = 'startsWith(x, "a")',
linters = string_boundary_linter()
)
#> ℹ No lints found.
lint(
text = 'endsWith(x, "z")',
linters = string_boundary_linter()
)
#> ℹ No lints found.
# If missing values are present, the suggested alternative wouldn't be strictly
# equivalent, so this linter can also be turned off in such cases.
lint(
text = 'grepl("z$", x)',
linters = string_boundary_linter(allow_grepl = TRUE)
)
#> ℹ No lints found.