
Require usage of startsWith() and endsWith() over grepl()/substr() versions
Source: R/string_boundary_linter.R
string_boundary_linter.RdstartsWith() 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()wherebyNAinput maps toFALSEoutput, 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.