rlang 0.4.0
Tidy evaluation
Interpolate function inputs with the curly-curly operator
The main change of this release is the new tidy evaluation operator
{{. This operator abstracts the quote-and-unquote idiom into a
single interpolation step:
my_wrapper <- function(data, var, by) {
data %>%
group_by({{ by }}) %>%
summarise(average = mean({{ var }}, na.rm = TRUE))
}
{{ var }} is a shortcut for !!enquo(var) that should be easier on
the eyes, and easier to learn and teach.
Note that for multiple inputs, the existing documentation doesn't
stress enough that you can just pass dots straight to other tidy eval
functions. There is no need for quote-and-unquote unless you need to
modify the inputs or their names in some way:
my_wrapper <- function(data, var, ...) {
data %>%
group_by(...) %>%
summarise(average = mean({{ var }}, na.rm = TRUE))
}
More robust .env pronoun
Another improvement to tidy evaluation should make it easier to use
the .env pronoun. Starting from this release, subsetting an object
from the .env pronoun now evaluates the corresponding symbol. This
makes .env more robust, in particular in magrittr pipelines. The
following example would previously fail:
foo <- 10
mtcars %>% mutate(cyl = cyl * .env$foo)
This way, using the .env pronoun is now equivalent to unquoting a
constant objects, but with an easier syntax:
mtcars %>% mutate(cyl = cyl * !!foo)
Note that following this change, and despite its name, .env is no
longer referring to a bare environment. Instead, it is a special
shortcut with its own rules. Similarly, the .data pronoun is not
really a data frame.
New functions and features
-
New
pairlist2()function with splicing support. It preserves
missing arguments, which makes it useful for lists of formal
parameters for functions. -
is_bool()is a scalar type predicate that checks whether its input
is a singleTRUEorFALSE. Likeis_string(), it returns
FALSEwhen the input is missing. This is useful for type-checking
function arguments (#695). -
is_string()gains astringargument.is_string(x, "foo")is a
shortcut foris_character(x) && length(x) == 1 && identical(x, "foo"). -
Lists of quosures now have pillar methods for display in tibbles.
-
set_names()now names unnamed input vectors before applying a
function. The following expressions are now equivalent:letters %>% set_names() %>% set_names(toupper) letters %>% set_names(toupper) -
You can now pass a character vector as message argument for
abort(),warn(),inform(), andsignal(). The vector is
collapsed to a single string with a"\n"newline separating each
element of the input vector (#744). -
maybe_missing()gains adefaultargument. -
New functions for weak references:
new_weakref(),weakref_key(),
weakref_value(), andis_weakref()(@wch, #787).
Performance
-
The performance of
exec()has been improved. It is now on the same
order of performance asdo.call(), though slightly slower. -
call2()now uses the newpairlist2()function internally. This
considerably improves its performance. This also means it now
preserves empty arguments:call2("fn", 1, , foo = ) #> fn(1, , foo = )
Bugfixes and small improvements
-
with_handlers()now installs calling handlers first on the stack,
no matter their location in the argument list. This way they always
take precedence over exiting handlers, which ensures their side
effects (such as logging) take place (#718). -
In rlang backtraces, the
global::prefix is now only added when
the function directly inherits from the global environment.
Functions inheriting indirectly no longer have a namespace
qualifier (#733). -
options(error = rlang::entrace)now has better support for errors
thrown from C (#779). It also saves structured errors in theerror
field ofrlang::last_error(). -
ns_env()andns_env_name()(experimental functions) now support
functions and environments consisently. They also require an
argument from now on. -
is_interactive()is aware of theTESTTHATenvironment variable and
returnsFALSEwhen it is"true"(@jennybc, #738). -
fn_fmls()and variants no longer coerce their input to a
closure. Instead, they throw an error. -
Fixed an issue in knitr that caused backtraces to print even when
error = TRUE. -
The return object from
as_function()now inherits from
"function"(@richierocks, #735).
Lifecycle
We commit to support 5 versions of R. As R 3.6 is about to be
released, rlang now requires R 3.2 or greater. We're also continuing
our efforts to streamline and narrow the rlang API.
-
modify()andprepend()(two experimental functions marked as in
the questioning stage since rlang 0.3.0) are now deprecated. Vector
functions are now out of scope for rlang. They might be revived in
the vctrs or funs packages. -
exiting()is soft-deprecated becausewith_handlers()treats
handlers as exiting by default. -
The vector constructors like
lgl()ornew_logical()are now in
the questioning stage. They are likely to be moved to the vctrs
package at some point. Same for the missing values shortcuts like
na_lgl. -
as_logical(),as_integer(), etc have been soft-deprecated in
favour ofvctrs::vec_cast(). -
type_of(),switch_type(),coerce_type(), and friends are
soft-deprecated. -
The encoding and locale API was summarily archived. This API didn't
bring any value and wasn't used on CRAN. -
lang_type_of(),switch_lang(), andcoerce_lang()were
archived. These functions were not used on CRAN or internally. -
Subsetting quosures with
[or[[is soft-deprecated. -
All functions that were soft-deprecated, deprecated, or defunct in
previous releases have been bumped to the next lifecycle stage.