NEWS.md

rlang (development version)

rlang 1.1.3

rlang 1.1.2

rlang 1.1.1

rlang 1.1.0

Life cycle changes

Main new features

It's normally TRUE by default, but if a warning is chained to an error or a message is chained to a warning or error (downgraded chaining), .inherit defaults to FALSE (#1573).

<[`data-masking`][rlang::args_data_masking]>

Miscellaneous fixes and features

rlang 1.0.6

rlang 1.0.5

rlang 1.0.4

rlang 1.0.3

Error in `my_function()`: Caused by error in `their_function()`: ! Message.

In addition, if you store the argument name of a failing input in the arg error field, the argument is also highlighted in the backtrace.

Instead of:

cli::cli_abort("{.arg {arg}} must be a foobar.", call = call)

You can now write this to benefit from arg highlighting:

cli::cli_abort("{.arg {arg}} must be a foobar.", arg = arg, call = call)

rlang 1.0.2

rlang 1.0.1

rlang 1.0.0

Major changes

This release focuses on the rlang errors framework and features extensive changes to the display of error messages.

To help with these cases, abort() now takes a call argument that you can set to caller_env() or parent.frame() when used in a helper function. The function call corresponding to this environment is retrieved and stored in the condition.

Breaking changes

We've noticed several packages failing after this change because they were using .data outside of a data-masking context. For instance the by argument of dplyr::join() is not data-masked. Previously dplyr::join(by = .data$foo) would silently be interpreted as dplyr::join(by = NULL). This is now an error.

Another issue is using .data inside ggplot2::labs(...). This is not allowed since labs() isn't data-masked.

We've noticed some packages do not check for NULL results from call_name(). Note that many complex calls such as foo()(), foo$bar() don't have a "name" and cause a NULL result. This is why you should always check for NULL results when using call_name().

We've added the function is_call_simple() to make it easier to work safely with call_name(). The invariant is that call_name() always returns a string when is_call_simple() returns TRUE. Conversely it always returns NULL when is_call_simple() retuns FALSE.

Consider using is_call() or just remove the expression check. In many cases it is fine letting all objects go through when an expression is expected. For instance you can inject objects directly inside dplyr arguments:

x <- seq_len(nrow(data)) dplyr::mutate(data, col = !!x)

Since environment forwarding is easy to mess up, and since the feature is aimed towards end users, as_function() now defaults to the global environment. Supply an environment explicitly if that is not correct in your case.

Fixes and features

tidyeval

rlang errors

See https://rlang.r-lib.org/reference/topic-condition-customisation.html to customise this new display.

This special formatting is not applied when abort(), warn(), and inform() are called from another namespace than rlang. See https://rlang.r-lib.org/reference/topic-condition-formatting.html if you'd like to use cli to format condition messages in your package.

For convenience, a fully unnamed vector is interpreted as a vector of "*" bullets.

Backtraces

The display of backtraces for unexpected errors (in chunks where error is unset or set to FALSE) is still controlled by rlang_backtrace_on_error.

If you show rlang backtraces in a knitted document, also set this in a hidden chunk to trim the knitr context from the backtraces:

options( rlang_trace_top_env = environment() )

This change replaces an ad hoc mechanism that caused bugs in corner cases (#1205).

Argument intake

We have added check_dots_empty0(). It has a different UI but is almost as efficient as checking for missing(...). Use this in very low level functions where a couple microseconds make a difference.

R APIs

call_standardise() is deprecated in favour of call_match().

rlang 0.4.12

rlang 0.4.11

rlang 0.4.10

rlang 0.4.9

Breaking changes

New features

Bugfixes and improvements

rlang 0.4.8

rlang 0.4.7

This change simplifies the display (#851) and makes it possible to rethow errors from a calling handler rather than an exiting handler, which we now think is more appropriate because it allows users to recover() into the error.

rlang 0.4.6

rlang 0.4.5

rlang 0.4.4

rlang 0.4.3

A single pair of braces triggers normal glue interpolation:

```r df <- data.frame(x = 1:3)

suffix <- "foo" df %>% dplyr::mutate("var_{suffix}" := x * 2) #> x var_foo #> 1 1 2 #> 2 2 4 #> 3 3 6 ```

Using a pair of double braces is for labelling a function argument. Technically, this is shortcut for "{as_label(enquo(arg))}". The syntax is similar to the curly-curly syntax for interpolating function arguments:

```r my_wrapper <- function(data, var, suffix = "foo") { data %>% dplyr::mutate("{{ var }}_{suffix}" := {{ var }} * 2) } df %>% my_wrapper(x) #> x x_foo #> 1 1 2 #> 2 2 4 #> 3 3 6

df %>% my_wrapper(sqrt(x)) #> x sqrt(x)_foo #> 1 1 2.000000 #> 2 2 2.828427 #> 3 3 3.464102 ```

rlang 0.4.2

Concretely, this is a way of breaking up lazy generation of error messages with conditionMessage() into three independent parts. This provides a lot of flexibility for hierarchies of error classes, for instance you could inherit the body of an error message from a parent class while overriding the header and footer.

rlang 0.4.1

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

``` letters %>% set_names() %>% set_names(toupper)

letters %>% set_names(toupper) ```

Performance

call2("fn", 1, , foo = ) #> fn(1, , foo = )

Bugfixes and small improvements

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.

rlang 0.3.2

rlang 0.3.1

This patch release polishes the new backtrace feature introduced in rlang 0.3.0 and solves bugs for the upcoming release of purrr 0.3.0. It also features as_label() and as_name() which are meant to replace quo_name() in the future. Finally, a bunch of deparsing issues have been fixed.

Backtrace fixes

r if (requireNamespace("rlang", quietly = TRUE)) { options(error = rlang::entrace) }

This handler also works as a calling handler:

r with_handlers( error = calling(entrace), foo(bar) )

However it's often more practical to use with_abort() in that case:

r with_abort(foo(bar))

as_label() and as_name()

The new as_label() and as_name() functions should be used instead of quo_name() to transform objects and quoted expressions to a string. We have noticed that tidy eval users often use quo_name() to extract names from quosured symbols. This is not a good use for that function because the way quo_name() creates a string is not a well defined operation.

For this reason, we are replacing quo_name() with two new functions that have more clearly defined purposes, and hopefully better names reflecting those purposes. Use as_label() to transform any object to a short human-readable description, and as_name() to extract names from (possibly quosured) symbols.

Create labels with as_label() to:

We expect as_label() to gain additional parameters in the future, for example to control the maximum width of a label. The way an object is labelled is thus subject to change.

On the other hand, as_name() transforms symbols back to a string in a well defined manner. Unlike as_label(), as_name() guarantees the roundtrip symbol -> string -> symbol.

In general, if you don't know for sure what kind of object you're dealing with (a call, a symbol, an unquoted constant), use as_label() and make no assumption about the resulting string. If you know you have a symbol and need the name of the object it refers to, use as_name(). For instance, use as_label() with objects captured with enquo() and as_name() with symbols captured with ensym().

Note that quo_name() will only be soft-deprecated at the next major version of rlang (0.4.0). At this point, it will start issuing once-per-session warnings in scripts, but not in packages. It will then be deprecated in yet another major version, at which point it will issue once-per-session warnings in packages as well. You thus have plenty of time to change your code.

Minor fixes and features

rlang 0.3.0

Breaking changes

The rlang API is still maturing. In this section, you'll find hard breaking changes. See the life cycle section below for an exhaustive list of API changes.

quo_text(sym("foo+")) #> [1] "`foo+`"

This caused a number of issues in reverse dependencies as quo_text() tends to be used for converting symbols to strings. quo_text() and quo_name() should not be used for this purpose because they are general purpose deparsers. These functions should generally only be used for printing outputs or creating default labels. If you need to convert symbols to strings, please use as_string() rather than quo_text().

We have extended the documentation of ?quo_text and ?quo_name to make these points clearer.

r call_modify(call, arg = NULL) # Add `arg = NULL` to the call call_modify(call, arg = zap()) # Remove the `arg` argument from the call

Summary

The changes for this version are organised around three main themes: error reporting, tidy eval, and tidy dots.

abort() also gains a parent argument. This is meant for situations where you're calling a low level API (to download a file, parse a JSON file, etc) and would like to intercept errors with base::tryCatch() or rlang::with_handlers() and rethrow them with a high-level message. Call abort() with the intercepted error as the parent argument. When the user prints rlang::last_error(), the backtrace will be shown in two sections corresponding to the high-level and low-level contexts.

In order to get segmented backtraces, the low-level error has to be thrown with abort(). When that's not the case, you can call the low-level function within with_abort() to automatically promote all errors to rlang errors.

Conditions and errors

Consequently all arguments have been renamed and prefixed with a dot (to limit naming conflicts between arguments and metadata names).

Tidy dots

!!! disallows:

Quoting functions used to automatically wrap language objects in lists to make them spliceable. This behaviour is now soft-deprecated and it is no longer valid to write !!!enquo(x). Please unquote scalar objects with !! instead.

Tidy eval

Environments

old <- env_bind(env, foo = "foo", bar = "bar") env_bind(env, !!!old)

Calls

Other improvements and fixes

Lifecycle

Soft-deprecated functions and arguments

rlang 0.3.0 introduces a new warning mechanism for soft-deprecated functions and arguments. A warning is issued, but only under one of these circumstances:

In addition, deprecation warnings appear only once per session in order to not be disruptive.

Deprecation warnings shouldn't make R CMD check fail for packages using testthat. However, expect_silent() can transform the warning to a hard failure.

tidyeval

Miscellaneous

This change concerns env_depth(), env_poke_parent(), env_parent<-, env_tail(), set_env(), env_clone(), env_inherits(), env_bind(), scoped_bindings(), with_bindings(), env_poke(), env_has(), env_get(), env_names(), env_bind_exprs() and env_bind_fns().

Deprecated functions and arguments

Deprecated functions and arguments issue a warning inconditionally, but only once per session.

``` # Bad rlang::expr(mean(rlang::UQ(var) * 100))

# Ok rlang::expr(mean(UQ(var) * 100))

# Good rlang::expr(mean(!!var * 100)) ```

Although soft-deprecated since rlang 0.2.0, UQ() and UQS() can still be used for now.

Defunct functions and arguments

Defunct functions and arguments throw an error when used.

Functions and arguments in the questioning stage

We are no longer convinced these functions are the right approach but we do not have a precise alternative yet.

rlang 0.2.2

This is a maintenance release that fixes several garbage collection protection issues.

rlang 0.2.1

This is a maintenance release that fixes several tidy evaluation issues.

rlang 0.2.0

This release of rlang is mostly an effort at polishing the tidy evaluation framework. All tidy eval functions and operators have been rewritten in C in order to improve performance. Capture of expression, quasiquotation, and evaluation of quosures are now vastly faster. On the UI side, many of the inconveniences that affected the first release of rlang have been solved:

See the first section below for a complete list of changes to the tidy evaluation framework.

This release also polishes the rlang API. Many functions have been renamed as we get a better feel for the consistency and clarity of the API. Note that rlang as a whole is still maturing and some functions are even experimental. In order to make things clearer for users of rlang, we have started to develop a set of conventions to document the current stability of each function. You will now find "lifecycle" sections in documentation topics. In addition we have gathered all lifecycle information in the ?rlang::lifecycle help page. Please only use functions marked as stable in your projects unless you are prepared to deal with occasional backward incompatible updates.

Tidy evaluation

Technically the !! operator has the same precedence as unary - and +. This means that !!a:b and !!a + b are equivalent to (!!a):b and (!!a) + b. On the other hand !!a^b and !!a$b are equivalent to!!(a^b) and !!(a$b).

In addition, enexprs() is like enquos() but like exprs() it returns bare expressions. And ensyms() expects strings or symbols.

select_one <- function(df, var) { df %>% dplyr::select(!!enquo(var)) }

Technically, this is because enquo() now also captures arguments in parents of the current environment rather than just in the current environment. The flip side of this increased flexibility is that if you made a typo in the name of the variable you want to capture, and if an object of that name exists anywhere in the parent contexts, you will capture that object rather than getting an error.

expr(`!!`(var)) quo(call(`!!!`(var)))

This is consistent with the way native R operators parses to function calls. These new functional forms are to be preferred to UQ() and UQS(). We are now questioning the latter and might deprecate them in a future release.

Conditions

Environments

Various features

Bugfixes

API changes

The rlang API is maturing and still in flux. However we have made an effort to better communicate what parts are stable. We will not introduce breaking changes for stable functions unless the payoff for the change is worth the trouble. See ?rlang::lifecycle for the lifecycle status of exported functions.

In rlang 0.1 calls were called "language" objects in order to follow the R type nomenclature as returned by base::typeof(). We wanted to avoid adding to the confusion between S modes and R types. With hindsight we find it is better to use more meaningful type names.

Following this new terminology, the new functions as_data_mask() and new_data_mask() replace as_overscope() and new_overscope(). as_data_mask() has also a more consistent interface. These functions are only meant for developers of tidy evaluation interfaces.

Breaking changes

Upcoming breaking changes

In addition, lang_head() and lang_tail() are soft-deprecated without replacement because these are low level accessors that are rarely needed.

rlang 0.1.6

rlang 0.1.4

rlang 0.1.2

This hotfix release makes rlang compatible with the R 3.1 branch.

rlang 0.1.1

This release includes two important fixes for tidy evaluation:

New functions:

UI improvements:

Bugfixes:

rlang 0.1.0

Initial release.



hadley/rlang documentation built on April 24, 2024, 1:05 a.m.