Fixes for CRAN checks.
Progress towards making rlang conformant with the public C API ofR.
env_browse() andenv_is_browsed() arenow defunct as they require an API that is no longer available topackages (#1727).
The SEXP iterator of the rlang C library (used in r-lib/memtools)is now behind a feature flag because it requires private API accessors.Compile rlang with-DRLANG_USE_PRIVATE_ACCESSORS to enableit.
env_unlock() is now defunct because recent versionsof R no long make it possible to unlock an environment (#1705). Makesure to use an up-to-date version of pkgload (>= 1.4.0) followingthis change.
is_dictionaryish() now will return TRUE for NULL(@ilovemane,#1712).
Added missing C levelr_dyn_raw_push_back() andr_dyn_chr_push_back() utilities (#1699).
last_trace() hyperlinks now use the modernx-r-run format (#1678).
Fix for CRAN checks.
%||% is now reexported from base on newer Rversions. This avoids conflict messages when attaching or importingrlang.
Fixed an off-by-one typo in the traceback source column location(#1633).
abort() now respects the base R global option,options(show.error.messages = FALSE) (#1630).
obj_type_friendly() now only displays the firstclass of S3 objects (#1622).
expr_label() now has back-compatility with respectto changes made by R version 4.4 andis.atomic(NULL)(#1655)
Performance improvement in.rlang_cli_compat()(#1657).
englue() now allows omitting{{. Thisis to make it easier to embed in external functions that need to supporteither{ and{{ (#1601).
Fix for CRAN checks.
stop_input_type() now handlesI() inputliterally inarg (#1607,
parse_expr() andparse_exprs() are nowfaster whengetOption("keep.source") isTRUE(#1603).
dots_splice() is deprecated. This function waspreviously in the questioning lifecycle stage as we were moving towardsthe explicit!!! splicing style.
flatten(),squash(), and their variantsare deprecated in favour ofpurrr::list_flatten() andpurrr::list_c().
child_env() is deprecated in favour ofenv() which has supported creating child environments forseveral years now.
last_error() andoptions(rlang_backtrace_on_error = "full") now print thefull backtrace tree by default (except for some hidden frames). Thesimplified backtraces tended to hide important context too often. Now weshow intervening frames in a lighter colour so that they don’t distractfrom the important parts of the backtraces but are still easilyinspectable.
global_entrace(),last_warnings(), andlast_messages() now support knitr documents.
Newrlang_backtrace_on_warning_report global option.This is useful in conjunction withglobal_entrace() to getbacktraces on warnings inside RMarkdown documents.
global_entrace() andentrace() now stopentracing warnings and messages after 20 times. This is to avoid a largeoverhead when 100s or 1000s of warnings are signalled in a loop(#1473).
abort(),warn(), andinform() gain an.inherit parameter. Thiscontrols whetherparent is inherited. IfFALSE,cnd_inherits() andtry_fetch() do not match chained conditions acrossparents.
It’s normallyTRUE by default, but if a warning ischained to an error or a message is chained to a warning or error(downgraded chaining),.inherit defaults toFALSE (#1573).
try_fetch() now looks up condition classes acrosschained errors (#1534). This makestry_fetch() insensitiveto changes of implementation or context of evaluation that cause aclassed error to suddenly get chained to a contextual error.
englue() gainedenv,error_arg, anderror_call arguments to supportbeing wrapped in another function (#1565).
The data-masking documentation for arguments has been importedfrom dplyr. You can link to it by starting an argument documentationwith this button:
<[`data-masking`][rlang::args_data_masking]>enquos() and friends gain a.ignore_null argument (#1450).
Newenv_is_user_facing() function to determine if anevaluation frame corresponds to a direct usage by the end user (from theglobal environment or a package being tested) or indirect usage by athird party function. The return value can be overridden by setting the"rlang_user_facing" global option.
Newcheck_data_frame() andcheck_logical() functions instandalone-types-check.R (#1587,
Addedallow_infinite argument tocheck_number_whole() (#1588,
The lifecycle standalone file has been updated to match themodern lifecycle tools.
parse_expr() now supports vectors of lines(#1540).
Quosures can now be consistently concatenated to lists ofquosures (#1446).
Fixed a memory issue that caused excessive duplication inlist2() and friends (#1491).
Embraced empty arguments are now properly detected and trimmed byquos() (#1421).
Fixed an edge case that causedenquos(.named = NULL)to return a named list (#1505).
expr_deparse() now deparses the embrace operator{{ on a single line (#1511).
zap_srcref() has been rewritten in C for efficiency(#1513).
zap_srcref() now supports expressionvectors.
The non-error path ofcheck_dots_unnamed() has beenrewritten in C for efficiency (#1528).
Improved error messages inenglue() (#1531) and inglue strings in the LHS of:= (#1526).
englue() now requires size 1 outputs (#1492). Thisprevents surprising errors or inconsistencies when an interpolated inputof size != 1 makes its way into the glue string.
arg_match() now throws correct error when supplied amissing value or an empty vector (#1519).
is_integerish() now handles negative doubles moreconsistently with positive ones (
Newcheck_logical() instandalone-types-check.R (#1560).
quo_squash() now squashes quosures in functionposition (#1509).
is_expression() now recognises quoted functions(#1499). It now also recognises non-parsable attributes(#1475).
obj_address() now supports the missing argument(#1521).
Fixed acheck_installed() issue with packagesremoved during the current R session (#1561).
new_data_mask() is now slightly faster due to asmaller initial mask size and usage of the C level functionR_NewEnv() on R >=4.1.0 (#1553).
The C levelr_dyn_*_push_back() utilities are nowfaster (#1542).
The C levelr_lgl_sum() andr_lgl_which() helpers are now faster (#1577, withcontributions from
rlang is now compliant with-Wstrict-prototypes asrequested by CRAN (#1508).
as_closure(seq.int) now works (#1468).
rlang no longer stores errors and backtraces in aorg:r-lib environment on the search path.
The low-level functionerror_call() is now exported(#1474).
Fixed an issue that caused a failure about a missingis_character function when rlang is installed alongside anold version of vctrs (#1482).
Fixed an issue that caused multiline calls inbacktraces.
The C API functionr_lgl_which() now propagates thenames of the input (#1471).
Thepkg_version_info() function now allows== for package version comparison (#1469,
Fixed backtrace display with calls containing long lists ofarguments (#1456).
Newr_obj_type_friendly() function in the C library(#1463). It interfaces withobj_type_friendly() fromcompat-obj-type.R via a C callable.
is_installed() no longer throws an error withirregular package names.
is_installed() andcheck_installed()now properly detect that the base package is installed on older versionsof R (#1434).
Child errors may now have empty messages to enable thispattern:
Error in `my_function()`:Caused by error in `their_function()`:! Message.Therlib_bytes class now uses prettyunits to formatbytes. The bytes are now represented with decimal prefixes instead ofbinary prefixes.
Supplying a frame environment to thecall argumentofabort() now causes the corresponding function call inthe backtrace to be highlighted.
In addition, if you store the argument name of a failing input in thearg error field, the argument is also highlighted in thebacktrace.
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)abort(message = ) can now be a function. In thiscase, it is stored in theheader field and acts as acnd_header() method invoked when the message isdisplayed.
Newobj_type_oo() function incompat-obj-type.R (#1426).
friendly_type_of() fromcompat-obj-type.R (formerlycompat-friendly-type.R) is nowobj_type_friendly().
options(backtrace_on_error = "collapse") andprint(trace, simplify = "collapse") are deprecated. Theyfall back to"none" with a warning.
call_match() now better handles...whendots_expand = FALSE.
list2(!!!x) is now faster whenx is alist. It is now returned as is instead of being duplicated into a newlist.
abort() gains a.trace_bottom argumentto disambiguate from other.frame. This allowscli::cli_abort() to wrapabort() in such a waythat.internal mentions the correct package to report theerror in (#1386).
Thetranspose() compat is now more consistent withpurrr when inner names are not congruent (#1346).
Newreset_warning_verbosity() andreset_message_verbosity() functions. These reset theverbosity of messages signalled withwarn() andinform() with the.frequency argument. This isuseful for testing verbosity in your package (#1414).
check_dots_empty() now allows trailing missingarguments (#1390).
Calls to local functions that are not accessible through:: or::: are now marked with(local) in backtraces (#1399).
Error messages now mention indexed calls likefoo$bar().
Newenv_coalesce() function to copy bindings fromone environment to another. Unlike approaches based on looping with[[<-,env_coalesce() preserves active andlazy bindings.
Chaining errors at top-level (directly in the console instead ofin a function) no longer fails (#1405).
Warning style is propagated across parent errors in chained errormessages (#1387).
check_installed() now works within catch-alltryCatch(error = ) expressions (#1402,tidyverse/ggplot2#4845).
arg_match() andarg_match0() nowmention the correct call in case of type error (#1388).
abort() andinform() now print messagestostdout in RStudio panes (#1393).
is_installed() now detects unsealed namespaces(#1378). This fixes inconsistent behaviour when run within user onLoadhooks.
Source references in backtraces andlast_error()/last_trace() instructions are nowclickable in IDEs that support links (#1396).
compat-cli.R now supportsstyle_hyperlink().
abort(.homonyms = "error") now throws the expectederror (#1394).
env_binding_are_active() no longer accidentallytriggers active bindings (#1376).
Fixed bug inquo_squash() with nested quosurescontaining the missing argument.
Backtraces of parent errors are now reused on rethrow. Thisavoids capturing the same backtrace twice and solves consistencyproblems by making sure both errors in a chain have the samebacktrace.
Fixed backtrace oversimplification whencnd is abase error inabort(parent = cnd).
Internal errors thrown withabort(.internal = TRUE)now mention the name of the package the error should be reportedto.
Backtraces are now separated from error messages with a--- ruler line (#1368).
The internal bullet formatting routine now ignores unknown names(#1364). This makes it consistent with the cli package, increasesresilience against hard-to-detect errors, and increases forwardcompatibility.
abort() and friends no longer calls non-existentfunctions (e.g. cli::format_error() orcli::format_warning) when the installed version of cli istoo old (#1367, tidyverse/dplyr#6189).
Fixed an OOB subsetting error inabort().
Newrlang_call_format_srcrefs global option (#1349).Similar torlang_trace_format_srcrefs, this option allowsturning off the display of srcrefs in error calls. This can be usefulfor reproducibility but note that srcrefs are already disabled withintestthat by default.
abort(parent = NA) is now supported to indicate anunchained rethrow. This helpsabort() detect the conditionhandling context to create simpler backtraces where this context ishidden by default.
Whenparent is supplied,abort() nowloops over callers to detect the condition handler frame. This makes iteasier to wrap or extract condition handlers in functions withoutsupplying.frame.
Whenparent is supplied andcall pointsto the condition setup frame (e.g. withCallingHandlers() ortry_fetch()),call is replaced with the callerof that setup frame. This provides a more helpful default call.
is_call() is now implemented in C forperformance.
Fixed performance regression intrace_back().
Fixed a partial matching issue withheader,body, andfooter condition fields.
eval_tidy() calls are no longer mentioned in errormessages.
This release focuses on the rlang errors framework and featuresextensive changes to the display of error messages.
abort() now displays errors as fully bulleted lists.Error headers are displayed with a! prefix. Seehttps://rlang.r-lib.org/reference/topic-condition-customisation.htmlto customise the display of error messages.
abort() now displays a full chain of messages whenerrors are chained with theparent argument. Following thischange, you should update dplyr to version 1.0.8 to get proper errormessages.
abort() now displays function calls in which amessage originated by default. We have refrained from showing thesecalls until now to avoid confusing messages when an error is thrown froma helper function that isn’t relevant to users.
To help with these cases,abort() now takes acall argument that you can set tocaller_env()orparent.frame() when used in a helper function. Thefunction call corresponding to this environment is retrieved and storedin the condition.
cli formatting is now supported. Usecli::cli_abort() to get advanced formatting of errormessages, including indented bulleted lists. Seehttps://rlang.r-lib.org/reference/topic-condition-formatting.html.
Newtry_fetch() function for error handling. Werecommend to use it for chaining errors. It mostly works liketryCatch() with a few important differences.
Compared totryCatch(),try_fetch()preserves the call stack. This allows full backtrace capture and allowsrecover() to reach the error site.
Compared towithCallingHandler(),try_fetch() is able to handle stack overflow errors (thisrequires R 4.2, unreleased at the time of writing).
The tidy eval documentation has been fully rewritten to reflectcurrent practices. Access it through the “Tidy evaluation” and“Metaprogramming” menus onhttps://rlang.r-lib.org.
The.data object exported by rlang now fails whensubsetted instead of returningNULL. This new error helpsyou detect when.data is used in the wrong context.
We’ve noticed several packages failing after this change because theywere using.data outside of a data-masking context. Forinstance theby argument ofdplyr::join() isnot data-masked. Previouslydplyr::join(by = .data$foo)would silently be interpreted asdplyr::join(by = NULL).This is now an error.
Another issue is using.data insideggplot2::labs(...). This is not allowed sincelabs() isn’t data-masked.
call_name() now returnsNULL instead of"::" for calls of the formfoo::bar.
We’ve noticed some packages do not check forNULLresults fromcall_name(). Note that many complex calls suchasfoo()(),foo$bar() don’t have a “name” andcause aNULL result. This is why you should always checkforNULL results when usingcall_name().
We’ve added the functionis_call_simple() to make iteasier to work safely withcall_name(). The invariant isthatcall_name() always returns a string whenis_call_simple() returnsTRUE. Conversely italways returnsNULL whenis_call_simple()retunsFALSE.
is_expression() now returnsFALSE formanually constructed expressions that can’t be created by the parser. Itused to returnTRUE for any calls, including those thatcontain injected objects.
Consider usingis_call() or just remove the expressioncheck. In many cases it is fine letting all objects go through when anexpression is expected. For instance you can inject objects directlyinside dplyr arguments:
x <- seq_len(nrow(data))dplyr::mutate(data, col = !!x)If a string is supplied toas_function() instead ofan object (function or formula), the function is looked up in the globalenvironment instead of the calling environment. In general, passing afunction name as a string is brittle. It is easy to forget to pass theuser environment toas_function() and sometimes there is noobvious user environment. The support for strings should be considered aconvenience for end users only, not for programmers.
Since environment forwarding is easy to mess up, and since thefeature is aimed towards end users,as_function() nowdefaults to the global environment. Supply an environment explicitly ifthat is not correct in your case.
with_handlers(),call_fn(), andfriendly_type() are deprecated.
Theaction argument ofcheck_dots_used(),check_dots_unnamed(), andcheck_dots_empty() is deprecated in favour of the newerror argument which takes an error handler.
Many functions deprecated in rlang 0.2.0 and 0.3.0 have beenremoved from the package.
Newenglue() operator to allow string-embracingoutside of dynamic dots (#1172).
Newdata_sym() anddata_syms()functions to create calls of the form.data$foo.
.data now fails early when it is subsetted outsideof a data mask context. This provides a more informative error message(#804, #1133).
as_label() now better handles calls to infixoperators (#956, r-lib/testthat#1432). This change improvesauto-labelled expressions in data-masking functions liketibble(),mutate(), etc.
The{{ operator is now detected more strictly(#1087). If additional arguments are supplied through{, itis no longer interpreted as an injection operator.
The.ignore_empty argument ofenexprs()andenquos() no longer treats named arguments suppliedthrough... as empty, consistently withexprs() andquos() (#1229).
Fixed a hang when a quosure inheriting from a data mask isevaluated in the mask again.
Fixed performance issue when splicing classes that explicitlyinherit from list with!!! (#1140,r-lib/vctrs#1170).
Attributes of quosure lists are no longer modified by side effect(#1142).
enquo(),enquos() and variants nowsupport numbered dots like..1 (#1137).
Fixed a bug in the AST rotation algorithm that caused the!! operator to unexpectedly mutate injected objects(#1103).
Fixed AST rotation issue with!! involving binaryoperators (#1125).
try_fetch() is a flexible alternative to bothtryCatch() andwithCallingHandlers() (#503).It is also more efficient thantryCatch() and createsleaner backtraces.
Newcnd_inherits() function to detect a class in achain of errors (#1293).
Newglobal_entrace() function, a user-friendlyhelper for configuring errors in your RProfile. Call it to enrich allbase errors and warnings with an rlang backtrace. This enableslast_error(),last_warnings(),last_messages(), andbacktrace_on_errorsupport for all conditions.
Newglobal_handle() function to install a defaultconfiguration of error handlers. This currently callsglobal_entrace() andglobal_prompt_install().Expect more to come.
The “Error:” part of error messages is now printed by rlanginstead of R. This introduces several cosmetic and informative changesin errors thrown byabort():
Thecall field of error messages is now displayed,as is the default inbase::stop(). The call is onlydisplayed if it is a simple expression (e.g. no inlined function) andthe arguments are not displayed to avoid distracting from the errormessage. The message is formatted with the tidyverse style(code formatting by the cli package if available).
The source location is displayed (as inbase::stop()) ifcall carries a sourcereference. Source locations are not displayed when testthat is runningto avoid brittle snapshots.
Error headers are always displayed on their own line, with a"!" bullet prefix.
Seehttps://rlang.r-lib.org/reference/topic-condition-customisation.htmlto customise this new display.
The display of chained errors created with theparent argument ofabort() has been improved.Chains of errors are now displayed at throw time with the error prefix“Caused by error:”.
Theprint() method of rlang errors (commonly invokedwithlast_error()) has been improved:
inform() andwarn() messages can now besilenced with the global optionsrlib_message_verbosity andrlib_warning_verbosity.
abort() now outputs error messages tostdout in interactive sessions, following the same approachasinform().
Errors, warnings, and messages generated from rlang are nowformatted with cli. This means in practice that long lines arewidth-wrapped to the terminal size and user themes are applied. This iscurrently only the case for rlang messages.
This special formatting is not applied whenabort(),warn(), andinform() are called from anothernamespace than rlang. Seehttps://rlang.r-lib.org/reference/topic-condition-formatting.htmlif you’d like to use cli to format condition messages in yourpackage.
format_error_bullets() (used as a fallback insteadof cli) now treats:
"v" as green ticks (" " as indented line breaks"*" as normal bullets"!" as warning bulletsFor convenience, a fully unnamed vector is interpreted as a vector of"*" bullets.
abort() gains a.internal argument.When set toTRUE, a footer bullet is added tomessage to let the user know that the error is internal andthat they should report it to the package authors.
abort(),warn(), andinform() gain abody argument to supplyadditional bullets in the error message.
rlang conditions now haveas.character() methods.Use this generic on conditions to generate a whole error message,including theError: prefix. These methods are implementedas wrappers aroundcnd_message().
header andfooter methods can now bestored as closures in condition fields of the same name.
cnd_message() gains aprefix argumentto print the message with a full prefix, includingcallfield if present and parent messages if the condition ischained.
cnd_message() gains aninherit argumentto control whether to print the messages of parent errors.
Condition constructors now check for duplicate field names(#1268).
cnd_footer() now returns thefooterfield by default, if any.
warn() andinform() now signalconditions of classes"rlang_warning" and"rlang_message" respectively.
Thebody field of error conditions can now be acharacter vector.
The error returned bylast_error() is now stored onthe search path as the.Last.error binding of the"org:r-lib" environment. This is consistent with how theprocessx package records error conditions. Printing the.Last.error object is now equivalent to runninglast_error().
Addedis_error(),is_warning(), andis_message() predicates (#1220).
interrupt() no longer fails when interrupts aresuspended (#1224).
warn() now temporarily sets thewarning.length global option to the maximum value (8170).The default limit (1000 characters) is especially easy to hit when themessage contains a lot of ANSI escapes, as created by the crayon or clipackages (#1211).
entrace() andglobal_entrace() now logwarnings and messages with backtraces attached. Runlast_warnings() orlast_messages() to inspectthe warnings or messages emitted during the last command.
Internal errors now include a winch backtrace if installed. Theuser is invited to install it if not installed.
Display of rlang backtraces for expected errors in dynamicreports (chunks whereerror = TRUE in knitted documents andRStudio notebooks) is now controlled by therlang_backtrace_on_error_report option. By default, this isset to"none".
The display of backtraces forunexpected errors (in chunkswhereerror is unset or set toFALSE) is stillcontrolled byrlang_backtrace_on_error.
Thelast_error() reminder is no longer displayed inRStudio notebooks.
Aknitr::sew() method is registered forrlang_error. This makes it possible to consultlast_error() (the call must occur in a different chunk thanthe error) and to setrlang_backtrace_on_error_reportglobal options in knitr to display a backtrace for expected errors.
If you show rlang backtraces in a knitted document, also set this ina 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 cornercases (#1205).
Therlang_trace_top_env global option fortrace_back() now detects when backtraces are created withinknitr. If the option is not set, its default value becomesknitr::knit_global() when knitr is in progress (asdetermined fromknitr.in.progress global option). Thisprevents the knitr evaluation context from appearing in the backtraces(#932).
Namespace changes are now emboldened in backtraces(#946).
Functions defined in the global environments or in localexecution environments are now displayed with a space separator inbacktraces instead of:: and:::. This avoidsmaking it seem like these frame calls are valid R code ready to be typedin (#902).
Backtraces no longer contain inlined objects to avoid performanceissues in edge cases (#1069, r-lib/testthat#1223).
External backtraces in error chains are now separately displayed(#1098).
Trace capture now better handles wrappers of calling handler incase of rethrown chained errors.
Backtraces now print dangling srcrefs (#1206). Paths areshortened to show only three components (two levels of folder and thefile).
The root symbol in backtraces is now slightly different so thatit can’t be confused with a prompt character (#1207).
arg_match() gains amultiple argumentfor cases where zero or several matches are allowed (#1281).
New functioncheck_required() to check that anargument is supplied. It produces a more friendly error message thanforce() (#1118).
check_dots_empty(),check_dots_used(),andcheck_dots_unnamed() have been moved from ellipsis torlang. The ellipsis package is deprecated and will eventually bearchived.
We have addedcheck_dots_empty0(). It has a different UIbut is almost as efficient as checking formissing(...).Use this in very low level functions where a couple microseconds make adifference.
Thearg_nm argument ofarg_match0()must now be a string or symbol.
arg_match() now mentions the supplied argument(#1113).
is_installed() andcheck_installed()gain aversion argument (#1165).
check_installed() now consults therlib_restart_package_not_found global option to determinewhether to prompt users to install packages. This also disables therestart mechanism (see below).
check_installed() now signals errors of classrlib_error_package_not_found with arlib_restart_package_not_found restart. This allows callinghandlers to install the required packages and restart the check(#1150).
is_installed() andcheck_installed()now support DESCRIPTION-style version requirements like"rlang (>= 1.0)". They also gainversionandcompare arguments to supply requirementsprogrammatically.
check_installed() gains anactionargument that is called when the user chooses to install and updatemissing and outdated packages.
Newcheck_exclusive() function to check that onlyone argument of a set is supplied (#1261).
on_load() andrun_on_load() lets yourun.onLoad() expressions from any file of your package.on_package_load() runs expressions when another package isloaded. (#1284)
The new predicateis_call_simple() indicates whethera call has a name and/or a namespace. It provides two invariants:
Ifis_call_simple(x) isTRUE,call_name() always returns a string.
Ifis_call_simple(x, ns = TRUE) isTRUE,call_ns() always returns astring.
call_name() andcall_ns() now returnNULL with calls of the formfoo::bar(#670).
Newcurrent_call(),caller_call(), andframe_call() accessors. Newframe_fn()accessor.
env_has() and the corresponding C-level function nolonger force active bindings (#1292).
Newnames2<- replacement function that never addsmissing values when names don’t have names (#1301).
zap_srcref() now preserves attributes ofclosures.
Objects headers (as printed bylast_error(),env_print(), …) are now formatted using thecls class of the cli package.
as_function() gainsarg andcall arguments to provide contextual information abouterroring inputs.
is_expression() now returnsFALSE formanually constructed expressions that cannot be created by the Rparser.
New C callablerlang_env_unbind(). This is a wrapperaroundR_removeVarFromFrame() on R >= 4.0.0. On older Rthis wraps the R functionbase::rm(). Unlikerm(), this function does not warn (nor throw) when abinding does not exist.
friendly_type_of() now supports missingarguments.
env_clone() now properly clones active bindings andavoids forcing promises (#1228). On R < 4.0, promises are stillforced.
Fixed ans3_register() issue when the registeringpackage is a dependency of the package that exports the generic(#1225).
Addedcompat-vctrs.R file for robust manipulation ofdata frames in zero-deps packages.
Addedcompat-cli.R file to format message elementsconsistently with cli in zero-deps packages.
compat-purrr.R now longer includespluck* helpers; these used a defintion of pluck thatpredated purrr (#1159).*_cpl() has also been removed. Themap* wrappers now callas_function() so thatyou can pass short anonymous functions that use~(#1157).
exprs_auto_name() gains arepair_autoargument to make automatic names unique (#1116).
The.named argument ofdots_list() cannow be set toNULL to give the result default names. Withthis option, fully unnamed inputs produce a fully unnamed result withNULL names instead of a character vector of minimal"" names (#390).
is_named2() is a variant ofis_named()that always returnsTRUE for empty vectors (#191). It testsfor the property that each element of a vector is named rather than thepresence of anames attribute.
Newrlib_bytes class imported from the bench package(#1117). It prints and parses human-friendly sizes.
Theenv argument ofas_function() nowdefaults to the global environment. Its previous default was the callerofas_function(), which was rarely the correct environmentto look in. Since it’s hard to remember to pass the user environment andit’s sometimes tricky to keep track of it, it’s best to consider stringlookup as a convenience for end users, not for developers(#1170).
s3_register() no longer fails when generic does notexist. This prevents failures when users don’t have all the lastversions of packages (#1112).
Formulas are now deparsed according to the tidyverse style guide(~symbol without space and~ expression() witha space).
Newhash_file(), complementinghash(),to generate 128-bit hashes for the data within a file without loading itinto R (#1134).
Newenv_cache() function to retrieve a value orcreate it with a default if it doesn’t exist yet (#1081).
env_get() andenv_get_list() gain alast argument. Lookup stops in that environment. This canbe useful in conjunction withbase::topenv().
Newcall_match() function. It is likematch.call() but also supports matching missing argumentsto their defaults in the function definition (#875).
call_standardise() is deprecated in favour ofcall_match().
expr_deparse() now properly escapes\characters in symbols, argument names, and vector names(#1160).
friendly_type_of() (fromcompat-friendly-type.R) now supports matrices and arrays(#141).
Updatedenv_print() to useformat_error_bullets() and consistent tidyverse style(#1154).
set_names() now recycles names of size 1 to the sizeof the input, following the tidyverse recycling rules.
is_bare_formula() now handles thescoped argument consistently. The default has been changedtoTRUE for compatibility with the historical defaultbehaviour (#1115).
The “definition” API (dots_definitions() etc.) hasbeen archived.
Newis_complex() predicates to complete the family(#1127).
The C functionr_obj_address() now properly prefixesaddresses with the hexadecimal prefix0x on Windows(#1135).
obj_address() is now exported.
%<~% now actually works.
XXH3_64bits() from the XXHash library is now exposedas C callable under the namerlang_xxh3_64bits().
Fix for CRAN checks.
Fixed a gcc11 warning related tohash()(#1088).
Newhash() function to generate 128-bit hashes forarbitrary R objects using the xxHash library. The implementation ismodeled afterxxhashlite,created by
Newcheck_installed() function. Unlikeis_installed(), it asks the user whether to install missingpackages. If the user accepts, the packages are installed withpak::pkg_install() if available, orutils::install.packages() otherwise. If the session is noninteractive or if the user chooses not to install the packages, thecurrent evaluation is aborted (#1075).
rlang is now licensed as MIT (#1063).
Fixed an issue causing extra empty lines ininform()messages with.frequency (#1076,
expr_deparse() now correctly wraps code using:: and::: (#1072,
inject() evaluates its argument with!!,!!!, and{{ support.
Newenquo0() andenquos0() operatorsfor defusing function arguments without automatic injection(unquotation).
format_error_bullets() is no longer experimental.Themessage arguments ofabort(),warn(), andinform() are automatically passedto that function to make it easy to create messages with regular, info,and error bullets. See?format_error_bullets for moreinformation.
Newzap_srcref() function to recursively removesource references from functions and calls.
A new compat file for the zeallot operator%<-%is now available in the rlang repository.
New%<~% operator to define a variablelazily.
Newenv_browse() andenv_is_browsed()functions.env_browse() is equivalent to evaluatingbrowser() within an environment. It sets the environment tobe persistently browsable (or unsets it ifvalue = FALSE issupplied).
Functions created from quosures withas_function()now print in a more user friendly way.
Newrlang_print_backtrace C callable for debuggingfrom C interpreters (#1059).
The.data pronoun no longer skips functions (#1061).This solves a dplyr issue involving rowwise data frames and list-columnsof functions (tidyverse/dplyr#5608).
as_data_mask() now intialises environments of thecorrect size to improve efficiency (#1048).
eval_bare(),eval_tidy() (#961), andwith_handlers() (#518) now propagate visibility.
cnd_signal() now ignoresNULLinputs.
Fixed bug that prevented splicing a named empty vector with the!!! operator (#1045).
The exit status of is now preserved in non-interactive sessionswhenentrace() is used as anoptions(error = )handler (#1052, rstudio/bookdown#920).
next andbreak are now properlydeparsed as nullary operators.
Backtraces now include native stacks (e.g. from C code) when thewinch package is installedandrlang_trace_use_winch is set toTRUE(@krlmlr).
Compatibility with upcoming testthat 3 and magrittr 2releases.
get_env() now returns the proper environment withprimitive functions, i.e. the base namespace rather than the baseenvironment (r-lib/downlit#32).
entrace() no longer handles non-rlang errors thatcarry a backtrace. This improves compatibility with packages likecallr.
Backtraces of unhandled errors are now displayed withouttruncation in non-interactive sessions (#856).
is_interactive() no longer consults“rstudio.notebook.executing” option (#1031).
cnd_muffle() now returnsFALSE insteadof failing if the condition is not mufflable (#1022).
warn() andinform() gain a.frequency argument to control how frequently the warningor message should be displayed.
Newraw_deparse_str() function for converting a rawvector into a string of hexadecimal characters (
The backtraces of chained errors are no longer decomposed byerror context. Instead, the error messages are displayed as a tree toreflect the error ancestry, and the deepest backtrace in the ancestry isdisplayed.
This change simplifies the display (#851) and makes it possible torethow errors from a calling handler rather than an exiting handler,which we now think is more appropriate because it allows users torecover() into the error.
env_bind(),env_bind_active(),env_bind_lazy(),env_get(), andenv_get_list() have been rewritten in C.
env_poke() now supportszap() sentinelsfor removing bindings (#1012) and has better support for characters thatare not representable in the local encoding.
env_poke() has been rewritten in C forperformance.
The unicode translation warnings that appeared on Windows with R4.0 are now fixed.
env_unbind(inherit = TRUE) now only removes abinding from the first parent environment that has a binding. It used toremove the bindings from the whole ancestry. The new behaviour doesn’tguarantee that a scope doesn’t have a binding but it is safer.
env_has() is now rewritten in C forperformance.
dots_list() gains a.named argument forauto-naming dots (#957).
It is now possible to subset the.data pronoun withquosured symbols or strings (#807).
Expressions likequote(list("a b" = 1)) are nowproperly deparsed byexpr_deparse() (#950).
parse_exprs() now preserves names (#808). When asingle string produces multiple expressions, the names may be useful tofigure out what input produced which expression.
parse_exprs() now supports empty expressions(#954).
list2(!!!x) no longer evaluatesxmultiple times (#981).
is_installed() now properly handles apkg argument of length > 1. Before this it silentlytested the first element ofpkg only and thus alwaysreturnedTRUE if the first package was installed regardlessof the actual length ofpkg. (#991,
arg_match0() is a faster version ofarg_match() for use when performance is at a premium (#997,@krlmlr).
!!! now uses a combination oflength(),names(), and[[ to splice S3 and S4 objects.This produces more consistent behaviour thanas.list() on awider variety of vector classes (#945, tidyverse/dplyr#4931).set_names(),is_formula(), andnames2() are now implemented in C for efficiency.
The.data pronoun now accepts symbol subscripts(#836).
Quosure lists now explicitly inherit from"list".This makes them compatible with the vctrs package (#928).
All rlang options are now documented in a centralised place, see?rlang::faq-options (#899,
Fixed crash whenenv_bindings_are_lazy() getsimproper arguments (#923).
arg_match() now detects and suggests possible typosin provided arguments (
arg_match() now gives an error if argument is oflength greater than 1 and doesn’t exactly match the values input,similar to basematch.arg (#914,
You can now use glue syntax to unquote on the LHS of:=. This syntax is automatically available in all functionstaking dots withlist2() andenquos(), andthus most of the tidyverse. Note that if you use the glue syntax in an Rpackage, you need to import glue.
A single pair of braces triggers normal glue interpolation:
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 6Using 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 interpolatingfunction arguments:
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 6df%>%my_wrapper(sqrt(x))#> x sqrt(x)_foo#> 1 1 2.000000#> 2 2 2.828427#> 3 3 3.464102Fixed a bug in magrittr backtraces that caused duplicate calls toappear in the trace.
Fixed a bug in magrittr backtraces that caused wrong callindices.
Empty backtraces are no longer shown whenrlang_backtrace_on_error is set.
The tidy eval.env pronoun is now exported fordocumentation purposes.
warn() andabort() now check thateitherclass ormessage was supplied.inform() allows sending empty message as it is occasionallyuseful for building user output incrementally.
flatten() fails with a proper error when input can’tbe flattened (#868, #885).
inform() now consistently appends a final newline tothe message (#880).
cnd_body.default() is now properlyregistered.
cnd_signal() now uses the same approach asabort() to save unhandled errors tolast_error().
Parsable constants likeNaN andNA_integer_ are now deparsed byexpr_deparse()in their parsable form (#890).
Infix operators now stick to their LHS when deparsed byexpr_deparse() (#890).
Newcnd_header(),cnd_body() andcnd_footer() generics. These are automatically called byconditionMessage.rlang_error(), the default method for allrlang errors.
Concretely, this is a way of breaking up lazy generation of errormessages withconditionMessage() into three independentparts. This provides a lot of flexibility for hierarchies of errorclasses, for instance you could inherit the body of an error messagefrom a parent class while overriding the header and footer.
The reminder to calllast_error() is now lessconfusing thanks to a suggestion by
The functions prefixed inscoped_ have been renamedto use the more conventionallocal_ prefix. For instance,scoped_bindings() is nowlocal_bindings(). Thescoped_ functions will be deprecated in the nextsignificant version of rlang (0.5.0).
The.subclass argument ofabort(),warn() andinform() has been renamed toclass. This is for consistency with our conventions forclass constructors documented inhttps://adv-r.hadley.nz/s3.html#s3-subclassing.
inform() now prints messages to the standard outputby default in interactive sessions. This makes them appear more likenormal output in IDEs such as RStudio. In non-interactive sessions,messages are still printed to standard error to make it easy to redirectmessages when running R scripts (#852).
Fixed an error intrace_back() when the call stackcontains a quosured symbol.
Backtrace is now displayed in full when an error occurs innon-interactive sessions. Previously the backtraces of parent errorswere left out.
New experimental framework for creating bulleted error messages.See?cnd_message for the motivation and an overwiew of thetools we have created to support this approach. In particular,abort() now takes character vectors to assemble a bulletlist. Elements namedx are prefixed with a red cross,elements namedi are prefixed with a blue info symbol, andunnamed elements are prefixed with a bullet.
Capture of backtrace in the context of rethrowing an error froman exiting handler has been improved. ThetryCatch()context no longer leaks in the high-level backtrace.
Printing an error no longer recommends callinglast_trace(), unless called fromlast_error().
env_clone() no longer recreates active bindings andis now just an alias forenv2list(as.list(env)). Unlikeas.list() which returns the active binding function on R< 4.0, the value of active bindings is consistently used in allversions.
The display of rlang errors derived from parent errors has beenimproved. The simplified backtrace (as printed byrlang::last_error()) no longer includes the parent errors.On the other hand, the full backtrace (as printed byrlang::last_trace()) now includes the backtraces of theparent errors.
cnd_signal() has improved support for rlang errorscreated witherror_cnd(). It now records a backtrace ifthere isn’t one already, and saves the error so it can be inspected withrlang::last_error().
rlang errors are no longer formatted and saved throughconditionMessage(). This makes it easier to use aconditionMessage() method in subclasses created withabort(), which is useful to delay expensive generation oferror messages until display time.
abort() can now be called without error message.This is useful whenconditionMessage() is used to generatethe message at print-time.
Fixed an infinite loop ineval_tidy(). It occurredwhen evaluating a quosure that inherits from the mask itself.
env_bind()’s performance has been significantlyimproved by fixing a bug that caused values to be repeatedly looked upby name.
cnd_muffle() now checks that a restart exists beforeinvoking it. The restart might not exist if the condition is signalledwith a different function (such asstop(warning_cnd)).
trace_length() returns the number of frames in abacktrace.
Added internal utilitycnd_entrace() to add abacktrace to a condition.
rlang::last_error() backtraces are no longerdisplayed in red.
x %|% y now also works wheny is ofsame length asx (
Empty named lists are now deparsed more explicitly as"<named list>".
Fixedchr() bug causing it to returninvisibly.
The main change of this release is the new tidy evaluation operator{{. This operator abstracts the quote-and-unquote idiominto 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’tstress enough that you can just pass dots straight to other tidy evalfunctions. There is no need for quote-and-unquote unless you need tomodify the inputs or their names in some way:
my_wrapper <- function(data, var, ...) { data %>% group_by(...) %>% summarise(average = mean({{ var }}, na.rm = TRUE))}.envpronounAnother improvement to tidy evaluation should make it easier to usethe.env pronoun. Starting from this release, subsetting anobject from the.env pronoun now evaluates thecorresponding symbol. This makes.env more robust, inparticular in magrittr pipelines. The following example would previouslyfail:
foo <- 10mtcars %>% mutate(cyl = cyl * .env$foo)This way, using the.env pronoun is now equivalent tounquoting 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.
Newpairlist2() function with splicing support. Itpreserves missing arguments, which makes it useful for lists of formalparameters for functions.
is_bool() is a scalar type predicate that checkswhether its input is a singleTRUE orFALSE.Likeis_string(), it returnsFALSE when theinput is missing. This is useful for type-checking function arguments(#695).
is_string() gains astring argument.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 intibbles.
set_names() now names unnamed input vectors beforeapplying 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 forabort(),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() (
The performance ofexec() has been improved. It isnow on the same order of performance asdo.call(), thoughslightly slower.
call2() now uses the newpairlist2()function internally. This considerably improves its performance. Thisalso means it now preserves empty arguments:
call2("fn", 1, , foo = )#> fn(1, , foo = )with_handlers() now installs calling handlers firston the stack, no matter their location in the argument list. This waythey always take precedence over exiting handlers, which ensures theirside effects (such as logging) take place (#718).
In rlang backtraces, theglobal:: prefix is now onlyadded 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 bettersupport for errors thrown from C (#779). It also saves structured errorsin theerror field ofrlang::last_error().
ns_env() andns_env_name()(experimental functions) now support functions and environmentsconsisently. They also require an argument from now on.
is_interactive() is aware of theTESTTHAT environment variable and returnsFALSE when it is"true" (
fn_fmls() and variants no longer coerce their inputto a closure. Instead, they throw an error.
Fixed an issue in knitr that caused backtraces to print even whenerror = TRUE.
The return object fromas_function() now inheritsfrom"function" (
We commit to support 5 versions of R. As R 3.6 is about to bereleased, rlang now requires R 3.2 or greater. We’re also continuing ourefforts to streamline and narrow the rlang API.
modify() andprepend() (twoexperimental functions marked as in the questioning stage since rlang0.3.0) are now deprecated. Vector functions are now out of scope forrlang. They might be revived in the vctrs or funs packages.
exiting() is soft-deprecated becausewith_handlers() treats handlers as exiting bydefault.
The vector constructors likelgl() ornew_logical() are now in the questioning stage. They arelikely to be moved to the vctrs package at some point. Same for themissing values shortcuts likena_lgl.
as_logical(),as_integer(), etc havebeen 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 APIdidn’t bring any value and wasn’t used on CRAN.
lang_type_of(),switch_lang(), andcoerce_lang() were archived. These functions were not usedon CRAN or internally.
Subsetting quosures with[ or[[ issoft-deprecated.
All functions that were soft-deprecated, deprecated, or defunctin previous releases have been bumped to the next lifecyclestage.
Fixed protection issue reported by rchk.
The experimental optionrlang__backtrace_on_error isno longer experimental and has been renamed torlang_backtrace_on_error.
New “none” option forrlang_backtrace_on_error.
Unary operators applied to quosures now give better errormessages.
Fixed issue with backtraces of warnings promoted to error, andentraced viawithCallingHandlers(). The issue didn’t affectentracing via top leveloptions(error = rlang::entrace)handling.
This patch release polishes the new backtrace feature introduced inrlang 0.3.0 and solves bugs for the upcoming release of purrr 0.3.0. Italso featuresas_label() andas_name() whichare meant to replacequo_name() in the future. Finally, abunch of deparsing issues have been fixed.
Newentrace() condition handler. Add this to yourRProfile to enable rlang backtraces for all errors, including warningspromoted to errors:
if (requireNamespace("rlang",quietly =TRUE)) {options(error = rlang::entrace)}This handler also works as a calling handler:
with_handlers(error =calling(entrace),foo(bar))However it’s often more practical to usewith_abort() inthat case:
with_abort(foo(bar))with_abort() gains aclasses argumentto promote any kind of condition to an rlang error.
Newlast_trace() shortcut to print the backtracestored in thelast_error().
Backtrace objects now print in full by default.
Calls in backtraces are now numbered according to their positionin the call tree. The numbering is non-contiguous for simplifiedbacktraces because of omitted call frames.
catch_cnd() gains aclasses argument tospecify which classes of condition to catch. It returnsNULL if the expected condition could not be caught(#696).
as_label() andas_name()The newas_label() andas_name() functionsshould be used instead ofquo_name() to transform objectsand quoted expressions to a string. We have noticed that tidy eval usersoften usequo_name() to extract names from quosuredsymbols. This is not a good use for that function because the wayquo_name() creates a string is not a well definedoperation.
For this reason, we are replacingquo_name() with twonew functions that have more clearly defined purposes, and hopefullybetter names reflecting those purposes. Useas_label() totransform any object to a short human-readable description, andas_name() to extract names from (possibly quosured)symbols.
Create labels withas_label() to:
Display an object in a concise way, for example to labellise axesin a graphical plot.
Give default names to columns in a data frame. In this case,labelling is the first step before name repair.
We expectas_label() to gain additional parameters inthe future, for example to control the maximum width of a label. The wayan object is labelled is thus subject to change.
On the other hand,as_name() transforms symbols back toa string in a well defined manner. Unlikeas_label(),as_name() guarantees the roundtrip symbol -> string-> symbol.
In general, if you don’t know for sure what kind of object you’redealing with (a call, a symbol, an unquoted constant), useas_label() and make no assumption about the resultingstring. If you know you have a symbol and need the name of the object itrefers to, useas_name(). For instance, useas_label() with objects captured withenquo()andas_name() with symbols captured withensym().
Note thatquo_name() will only be soft-deprecated at thenext major version of rlang (0.4.0). At this point, it will startissuing once-per-session warnings in scripts, but not in packages. Itwill then be deprecated in yet another major version, at which point itwill issue once-per-session warnings in packages as well. You thus haveplenty of time to change your code.
Newis_interactive() function. It serves the samepurpose asbase::interactive() but also checks if knitr isin progress and provides an escape hatch. Usewith_interactive() andscoped_interactive() tooverride the return value ofis_interactive(). This isuseful in unit tests or to manually turn on interactive features inRMarkdown outputs
calling() now boxes its argument.
Newdone() function to box a value. Done boxes aresentinels to indicate early termination of a loop or computation. Forinstance, it will be used in the purrr package to allow users toshortcircuit a reduction or accumulation.
new_box() now accepts additional attributes passedtostructure().
Fixed a quotation bug with binary operators of zero or oneargument such as`/`(1) (#652). They are now deparsed andprinted properly as well.
Newcall_ns() function to retrieve the namespace ofa call. ReturnsNULL if the call is notnamespaced.
Top-level S3 objects are now deparsed properly.
Empty{ blocks are now deparsed on the sameline.
Fixed a deparsing issue with symbols containing non-ASCIIcharacters (#691).
expr_print() now handles[ and[[ operators correctly, and deparses non-syntactic symbolswith backticks.
call_modify() now respects ordering of unnamedinputs. Before this fix, it would move all unnamed inputs after namedones.
as_closure() wrappers now call primitives withpositional arguments to avoid edge case issues of argumentmatching.
as_closure() wrappers now dispatch properly onmethods defined in the global environment(tidyverse/purrr#459).
as_closure() now supports both base-style(e1 ande2) and purrr-style (.xand.y) arguments with binary primitives.
exec() takes.fn as first argumentinstead off, for consistency with other rlangfunctions.
Fixed infinite loop with quosures created inside a datamask.
Base errors set asparent of rlang errors are nowprinted correctly.
The rlang API is still maturing. In this section, you’ll find hardbreaking changes. See the life cycle section below for an exhaustivelist of API changes.
quo_text() now deparses non-syntactic symbols withbackticks:
quo_text(sym("foo+"))#> [1] "`foo+`"This caused a number of issues in reverse dependencies asquo_text() tends to be used for converting symbols tostrings.quo_text() andquo_name() should notbe used for this purpose because they are general purpose deparsers.These functions should generally only be used for printing outputs orcreating default labels. If you need to convert symbols to strings,please useas_string() rather thanquo_text().
We have extended the documentation of?quo_text and?quo_name to make these points clearer.
exprs() no longer flattens quosures.exprs(!!!quos(x, y)) is now equivalent toquos(x, y).
The sentinel for removing arguments incall_modify()has been changed fromNULL tozap(). Thisbreaking change is motivated by the ambiguity ofNULL withvalid argument values.
call_modify(call,arg =NULL)# Add `arg = NULL` to the callcall_modify(call,arg =zap())# Remove the `arg` argument from the callThe%@% operator now quotes its input and supportsS4 objects. This makes it directly equivalent to@ exceptthat it extracts attributes for non-S4 objects (#207).
Taking theenv_parent() of the empty environment isnow an error.
The changes for this version are organised around three main themes:error reporting, tidy eval, and tidy dots.
abort() now records backtraces automatically in theerror object. Errors thrown withabort() invite users tocallrlang::last_error() to see a backtrace and helpidentifying where and why the error occurred. The backtraces created byrlang (you can create one manually withtrace_back()) areprinted in a simplified form by default that removes implementationdetails from the backtrace. To see the full backtrace, callsummary(rlang::last_error()).
abort() also gains aparent argument. Thisis meant for situations where you’re calling a low level API (todownload a file, parse a JSON file, etc) and would like to intercepterrors withbase::tryCatch() orrlang::with_handlers() and rethrow them with a high-levelmessage. Callabort() with the intercepted error as theparent argument. When the user printsrlang::last_error(), the backtrace will be shown in twosections corresponding to the high-level and low-level contexts.
In order to get segmented backtraces, the low-level error has to bethrown withabort(). When that’s not the case, you can callthe low-level function withinwith_abort() to automaticallypromote all errors to rlang errors.
The tidy eval changes are mostly for developers of data maskingAPIs. The main user-facing change is that.data[[ is now anunquote operator so thatvar in.data[[var]]is never masked by data frame columns and always picked from theenvironment. This makes the pronoun safe for programming infunctions.
The!!! operator now supports all classed objectslike factors. It callsas.list() on S3 objects andas(x, "list") on S4 objects.
dots_list() gains several arguments to control howdots are collected. You can control the selection of arguments with thesame name with.homonyms (keep first, last, all, or abort).You can also elect to preserve empty arguments with.preserve_empty.
Newtrace_back() captures a backtrace. Compared tothe base R traceback, it contains additional structure about therelationship between frames. It comes with tools for automaticallyrestricting to frames after a certain environment on the stack, and tosimplify when printing. These backtraces are now recorded in errorsthrown byabort() (see below).
abort() gains aparent argument tospecify a parent error. This is meant for situations where a low-levelerror is expected (e.g. download or parsing failed) and you’d like tothrow an error with higher level information. Specifying the low-levelerror as parent makes it possible to partition the backtraces based onancestry.
Errors thrown withabort() now embed a backtrace inthe condition object. It is no longer necessary to record a trace with acalling handler for such errors.
with_abort() runs expressions in a context where allerrors are promoted to rlang errors and gain a backtrace.
Unhandled errors thrown byabort() are nowautomatically saved and can be retrieved withrlang::last_error(). The error prints with a simplifiedbacktrace. Callsummary(last_error()) to see the fullbacktrace.
New experimental optionrlang__backtrace_on_error todisplay backtraces alongside error messages. See?rlang::abort for supported options.
The newsignal() function completes theabort(),warn() andinform()family. It creates and signals a bare condition.
Newinterrupt() function to simulate an userinterrupt from R code.
cnd_signal() now dispatches messages, warnings,errors and interrupts to the relevant signalling functions(message(),warning(),stop() andthe C functionRf_onintr()). This makes it a good choice toresignal a captured condition.
Newcnd_type() helper to determine the type of acondition ("condition","message","warning","error" or"interrupt").
abort(),warn() andinform() now accepts metadata with.... Thedata are stored in the condition and can be examined by userhandlers.
Consequently all arguments have been renamed and prefixed with a dot(to limit naming conflicts between arguments and metadatanames).
with_handlers() treats bare functions as exitinghandlers (equivalent to handlers supplied totryCatch()).It also supports the formula shortcut for lambda functions (as inpurrr).
with_handlers() now produces a cleaner stacktrace.
The input types of!!! have been standardised.!!! is generally defined on vectors: it takes a vector(typically, a list) and unquotes each element as a separate argument.The standardisation makes!!! behave the same in functionstaking dots withlist2() and in quoting functions.!!! accepts these types:
Lists, pairlists, and atomic vectors. If they have a class, theyare converted withbase::as.list() to allow S3 dispatch.Following this change, objects like factors can now be spliced withoutdata loss.
S4 objects. These are converted withas(obj, "list")before splicing.
Quoted blocks of expressions, i.e. { }calls
!!! disallows:
Quoting functions used to automatically wrap language objects inlists to make them spliceable. This behaviour is now soft-deprecated andit is no longer valid to write!!!enquo(x). Please unquotescalar objects with!! instead.
dots_list(),enexprs() andenquos() gain a.homonyms argument to controlhow to treat arguments with the same name. The default is to keep them.Set it to"first" or"last" to keep only thefirst or last occurrences. Set it to"error" to raise aninformative error about the arguments with duplicated names.
enexprs() andenquos() now support.ignore_empty = "all" with named arguments as well(#414).
dots_list() gains a.preserve_emptyargument. WhenTRUE, empty arguments are stored as missingarguments (see?missing_arg).
dots_list(),enexprs() andenquos() gain a.check_assign argument. WhenTRUE, a warning is issued when a<- call isdetected in.... No warning is issued if the assignment iswrapped in brackets like{ a <- 1 }. The warning letsusers know about a possible typo in their code (assigning instead ofmatching a function parameter) and requires them to be explicit thatthey really want to assign to a variable by wrapping inparentheses.
lapply(list(quote(foo)), list2) no longer evaluatesfoo (#580).
You can now unquote quosured symbols as LHS of:=.The symbol is automatically unwrapped from the quosure.
Quosure methods have been defined for common operations like==. These methods fail with an informative error messagesuggesting to unquote the quosure (#478,#tidyverse/dplyr#3476).
as_data_pronoun() now accepts data masks. If themask has multiple environments, all of these are looked up whensubsetting the pronoun. Function objects stored in the mask arebypassed.
It is now possible to unquote strings in function position. Thisis consistent with how the R parser coerces strings to symbols. Thesetwo expressions are now equivalent:expr("foo"()) andexpr((!!"foo")()).
Quosures converted to functions withas_function()now support nested quosures.
expr_deparse() (used to print quosures at theconsole) now escapes special characters. For instance, newlines nowprint as"\n" (#484). This ensures that the roundtripparse_expr(expr_deparse(x)) is not lossy.
new_data_mask() now throws an error whenbottom is not a child oftop (#551).
Formulas are now evaluated in the correct environment withineval_tidy(). This fixes issues in dplyr and othertidy-evaluation interfaces.
New functionsnew_quosures() andas_quosures() to create or coerce to a list of quosures.This is a small S3 class that ensures two invariants on subsetting andconcatenation: that each element is a quosure and that the list isalways named even if only with a vector of empty strings.
env() now treats a single unnamed argument as theparent of the new environment. Consequently,child_env() isnow superfluous and is now in questioning life cycle.
Newcurrent_env() andcurrent_fn()functions to retrieve the current environment or the function beingevaluated. They are equivalent tobase::environment() andbase::sys.function() called without argument.
env_get() andenv_get_list() gain adefault argument to provide a default value fornon-existing bindings.
env_poke() now returns the old value invisiblyrather than the input environment.
The new functionenv_name() returns the name of anenvironment. It always adds the “namespace:” prefix to namespace names.It returns “global” instead of “.GlobalEnv” or “R_GlobalEnv”, “empty”instead of “R_EmptyEnv”. The companionenv_label() is likeenv_name() but returns the memory address for anonymousenvironments.
env_parents() now returns a named list. The namesare taken withenv_name().
env_parents() andenv_tail() now stopat the global environment by default. This can be changed with thelast argument. The empty environment is always a stoppingcondition so you can take the parents or the tail of an environment onthe search path without changing the default.
New predicatesenv_binding_are_active() andenv_binding_are_lazy() detect the kind of bindings in anenvironment.
env_binding_lock() andenv_binding_unlock() allows to lock and unlock multiplebindings. The predicateenv_binding_are_locked() tests ifbindings are locked.
env_lock() andenv_is_locked() lock anenvironment or test if an environment is locked.
env_print() pretty-prints environments. It shows thecontents (up to 20 elements) and the properties of theenvironment.
is_scoped() has been soft-deprecated and renamed tois_attached(). It now supports environments in addition tosearch names.
env_bind_lazy() andenv_bind_active()now support quosures.
env_bind_exprs() andenv_bind_fns() aresoft-deprecated and renamed toenv_bind_lazy() andenv_bind_active() for clarity and consistency.
env_bind(),env_bind_exprs(), andenv_bind_fns() now return the list of old binding values(or missing arguments when there is no old value). This makes it easy torestore the original environment state:
old <- env_bind(env, foo = "foo", bar = "bar")env_bind(env, !!!old)env_bind() now supports binding missing argumentsand removing bindings with zap sentinels.env_bind(env, foo = ) binds a missing argument andenv_bind(env, foo = zap()) removes thefoobinding.
Theinherit argument ofenv_get() andenv_get_list() has changed position. It now comes afterdefault.
scoped_bindings() andwith_bindings()can now be called without bindings.
env_clone() now recreates active bindingscorrectly.
env_get() now evaluates promises and active bindingssince these are internal objects which should not be exposed at the Rlevel (#554)
env_print() callsget_env() on itsargument, making it easier to see the environment of closures andquosures (#567).
env_get() now supports retrieving missing argumentswheninherit isFALSE.
is_call() now accepts multiple namespaces. Forinstanceis_call(x, "list", ns = c("", "base")) will matchifx islist() or if it’sbase::list():
call_modify() has better support for... and now treats it like a named argument.call_modify(call, ... = ) adds... to the callandcall_modify(call, ... = NULL) removes it.
call_modify() now preserves empty arguments. It isno longer necessary to usemissing_arg() to add a missingargument to a call. This is possible thanks to the new.preserve_empty option ofdots_list().
call_modify() now supports removing unexistingarguments (#393) and passing multiple arguments with the same name(#398). The new.homonyms argument controls how to treatthese arguments.
call_standardise() now handles primitive functionslike~ properly (#473).
call_print_type() indicates how a call is deparsedand printed at the console by R: prefix, infix, and specialform.
Thecall_ functions such ascall_modify() now correctly check that their input is theright type (#187).
New functionzap() returns a sentinel that instructsfunctions likeenv_bind() orcall_modify()that objects are to be removed.
New functionrep_named() repeats value along acharacter vector of names.
New functionexec() is a simpler replacement toinvoke() (#536).invoke() has beensoft-deprecated.
Lambda functions created from formulas withas_function() are now classed. Useis_lambda()to check a function was created with the formula shorthand.
is_integerish() now supports large double values(#578).
are_na() now requires atomic vectors(#558).
The operator%@% has now a replacement version toupdate attributes of an object (#207).
fn_body() always returns a{ block,even if the function has a single expression. For instancefn_body(function(x) do()) returnsquote({ do() }).
is_string() now returnsFALSE forNA_character_.
The vector predicates have been rewritten in C forperformance.
Thefinite argument ofis_integerish()is nowNULL by default. Missing values are now consideredas non-finite for consistency withbase::is.finite().
is_bare_integerish() andis_scalar_integerish() gain afinite argumentfor consistency withis_integerish().
flatten_if() andsquash_if() now handleprimitive functions likebase::is.list() aspredicates.
is_symbol() now accepts a character vector of namesto mach the symbol against.
parse_exprs() andparse_quos() nowsupport character vectors. Note that the output may be longer than theinput as each string may yield multiple expressions (such as"foo; bar").
parse_quos() now adds thequosuresclass to its output.
rlang 0.3.0 introduces a new warning mechanism for soft-deprecatedfunctions and arguments. A warning is issued, but only under one ofthese circumstances:
library() call.In addition, deprecation warnings appear only once per session inorder to not be disruptive.
Deprecation warnings shouldn’t make R CMD check fail for packagesusing testthat. However,expect_silent() can transform thewarning to a hard failure.
.data[[foo]] is now an unquote operator. Thisguarantees thatfoo is evaluated in the context rather thanthe data mask and makes it easier to treat.data[["bar"]]the same way as a symbol. For instance, this will help ensuring thatgroup_by(df, .data[["name"]]) andgroup_by(df, name) produce the same column name.
Automatic naming of expressions now uses a new deparser (stillunexported) instead ofquo_text(). Following this change,automatic naming is now compatible with all object types (viapillar::type_sum() if available), prevents multi-linenames, and ensuresname and.data[["name"]]are given the same default name.
Supplying a name with!!! calls is soft-deprecated.This name is ignored because only the names of the spliced vector areapplied.
Quosure lists returned byquos() andenquos() now have “list-of” behaviour: the types of newelements are checked when adding objects to the list. Consequently,assigning non-quosure objects to quosure lists is now soft-deprecated.Please coerce to a bare list withas.list()beforehand.
as_quosure() now requires an explicit environmentfor symbols and calls. This should typically be the environment in whichthe expression was created.
names() andlength() methods for datapronouns are deprecated. It is no longer valid to writenames(.data) orlength(.data).
Usingas.character() on quosures is soft-deprecated(#523).
Usingget_env() without supplying an environment isnow soft-deprecated. Please usecurrent_env() to retrievethe current environment.
The frame and stack API is soft-deprecated. Some of thefunctionality has been replaced bytrace_back().
Thenew_vector_along() family is soft-deprecatedbecause these functions are longer to type than the equivalentrep_along() orrep_named() calls without addedclarity.
Passing environment wrappers like formulas or functions toenv_ functions is now soft-deprecated. This internalgenericity was causing confusion (see issue #427). You should nowextract the environment separately before calling these functions.
This change concernsenv_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() andenv_bind_fns().
cnd_signal() now always installs a muffling restartfor non-critical conditions. Consequently the.mufflableargument has been soft-deprecated and no longer has any effect.
Deprecated functions and arguments issue a warning inconditionally,but only once per session.
CallingUQ() andUQS() with the rlangnamespace qualifier is deprecated as of rlang 0.3.0. Just use theunqualified forms instead:
# Badrlang::expr(mean(rlang::UQ(var) * 100))# Okrlang::expr(mean(UQ(var) * 100))# Goodrlang::expr(mean(!!var * 100))Although soft-deprecated since rlang 0.2.0,UQ() andUQS() can still be used for now.
Thecall argument ofabort() andcondition constructors is now deprecated in favour of storing fullbacktraces.
The.standardise argument ofcall_modify() is deprecated. Please usecall_standardise() beforehand.
Thesentinel argument ofenv_tail() hasbeen deprecated and renamed tolast.
Defunct functions and arguments throw an error when used.
as_dictionary() is now defunct.
The experimental functionrst_muffle() is nowdefunct. Please usecnd_muffle() instead. Unlike itspredecessor,cnd_muffle() is not generic. It is marked as acalling handler and thus can be passed directly towith_handlers() to muffle specific conditions (such asspecific subclasses of warnings).
cnd_inform(),cnd_warn() andcnd_abort() are retired and defunct. The oldcnd_message(),cnd_warning(),cnd_error() andnew_cnd() constructorsdeprecated in rlang 0.2.0 are now defunct.
Modifying a condition withcnd_signal() is defunct.In addition, creating a condition withcnd_signal() issoft-deprecated, please use the new function [signal()]instead.
inplace() has been renamed tocalling()to follow base R terminology more closely.
We are no longer convinced these functions are the right approach butwe do not have a precise alternative yet.
The functions from the restart API are now in the questioninglifecycle stage. It is not clear yet whether we want to recommendrestarts as a style of programming in R.
prepend() andmodify() are in thequestioning stage, as well asas_logical(),as_character(), etc. We are still figuring out what vectortools belong in rlang.
flatten(),squash() and their atomicvariants are now in the questioning lifecycle stage. They have slightlydifferent semantics than the flattening functions in purrr and we arecurrently rethinking our approach to flattening with the new typingfacilities of the vctrs package.
This is a maintenance release that fixes several garbage collectionprotection issues.
This is a maintenance release that fixes several tidy evaluationissues.
Functions with tidy dots support now allow splicing atomicvectors.
Quosures no longer capture the currentsrcref.
Formulas are now evaluated in the correct environment byeval_tidy(). This fixes issues in dplyr and othertidy-evaluation interfaces.
This release of rlang is mostly an effort at polishing the tidyevaluation framework. All tidy eval functions and operators have beenrewritten in C in order to improve performance. Capture of expression,quasiquotation, and evaluation of quosures are now vastly faster. On theUI side, many of the inconveniences that affected the first release ofrlang have been solved:
The!! operator now has the precedence of unary+ and- which allows a much more naturalsyntax:!!a > b only unquotesa rather thanthe wholea > b expression.
enquo() works in magrittr pipes:mtcars %>% select(!!enquo(var)).
enquos() is a variant ofquos() thathas a more natural interface for capturing multiple arguments and....
See the first section below for a complete list of changes to thetidy evaluation framework.
This release also polishes the rlang API. Many functions have beenrenamed as we get a better feel for the consistency and clarity of theAPI. Note that rlang as a whole is still maturing and some functions areeven experimental. In order to make things clearer for users of rlang,we have started to develop a set of conventions to document the currentstability of each function. You will now find “lifecycle” sections indocumentation topics. In addition we have gathered all lifecycleinformation in the?rlang::lifecycle help page. Please onlyuse functions marked as stable in your projects unless you are preparedto deal with occasional backward incompatible updates.
The backend forquos(),exprs(),list2(),dots_list(), etc is now written in C.This greatly improve the performance of dots capture, especially withthe splicing operator!!! which now scales much better(you’ll see a 1000x performance gain in some cases). The unquotingalgorithm has also been improved which makesenexpr() andenquo() more efficient as well.
The tidy eval!! operator now binds tightly. You nolonger have to wrap it in parentheses, i.e. !!x > y willonly unquotex.
Technically the!! operator has the same precedence asunary- 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 equivalentto!!(a^b) and!!(a$b).
The print method for quosures has been greatly improved. Quosuresno longer appear as formulas but as expressions prefixed with^; quosures are colourised according to their environment;unquoted objects are displayed between angular brackets instead of code(i.e. an unquoted integer vector is shown as<int: 1, 2> rather than1:2); unquotedS3 objects are displayed usingpillar::type_sum() ifavailable.
Newenquos() function to capture arguments. Ittreats... the same way asquos() but can alsocapture named arguments just likeenquo(), i.e. one levelup. By comparisonquos(arg) only captures the namearg rather than the expression supplied to thearg argument.
In addition,enexprs() is likeenquos() butlikeexprs() it returns bare expressions. Andensyms() expects strings or symbols.
It is now possible to useenquo() within a magrittrpipe:
select_one <- function(df, var) { df %>% dplyr::select(!!enquo(var))}Technically, this is becauseenquo() now also capturesarguments in parents of the current environment rather than just in thecurrent environment. The flip side of this increased flexibility is thatif you made a typo in the name of the variable you want to capture, andif an object of that name exists anywhere in the parent contexts, youwill capture that object rather than getting an error.
quo_expr() has been renamed toquo_squash() in order to better reflect that it is a lossyoperation that flattens all nested quosures.
!!! now accepts any kind of objects for consistency.Scalar types are treated as vectors of length 1. Previously onlysymbolic objects like symbols and calls were treated as such.
ensym() is a new variant ofenexpr()that expects a symbol or a string and always returns a symbol. If acomplex expression is supplied it fails with an error.
exprs() andquos() gain a.unquote_names arguments to switch off interpretation of:= as a name operator. This should be useful forprogramming on the language targetting APIs such as data.table.
exprs() gains a.named option toauto-label its arguments (#267).
Functions taking dots by value rather than by expression(e.g. regular functions, not quoting functions) have a more restrictedset of unquoting operations. They only support:= and!!!, and only at top-level. I.e.dots_list(!!! x) is valid but notdots_list(nested_call(!!! x)) (#217).
Functions taking dots withlist2() ordots_list() now support splicing ofNULLvalues.!!! NULL is equivalent to!!! list()(#242).
Capture operators now support evaluated arguments. Capturing aforced or evaluated argument is exactly the same as unquoting thatargument: the actual object (even if a vector) is inlined in theexpression. Capturing a forced argument occurs when you useenquo(),enexpr(), etc too late. It alsohappens when your quoting function is supplied tolapply()or when you try to quote the first argument of an S3 method (which isnecessarily evaluated in order to detect which class to dispatch to).(#295, #300).
Parentheses around!! are automatically removed.This makes the generated expression call cleaner:(!! sym("name"))(arg). Note that removing the parentheseswill never affect the actual precedence within the expression as theparentheses are only useful when parsing code as text. The parentheseswill also be added by R when printing code if needed (#296).
Quasiquotation now supports!! and!!!as functional forms:
expr(`!!`(var))quo(call(`!!!`(var)))This is consistent with the way native R operators parses to functioncalls. These new functional forms are to be preferred toUQ() andUQS(). We are now questioning thelatter and might deprecate them in a future release.
The quasiquotation parser now gives meaningful errors in cornercases to help you figure out what is wrong.
New getters and setters for quosures:quo_get_expr(),quo_get_env(),quo_set_expr(), andquo_set_env(). Compared toget_expr() etc, these accessors only work on quosures andare slightly more efficient.
quo_is_symbol() andquo_is_call() nowtake the same set of arguments asis_symbol() andis_call().
enquo() andenexpr() now deal withdefault values correctly (#201).
Splicing a list no longer mutates it (#280).
The new functionscnd_warn() andcnd_inform() transform conditions to warnings or messagesbefore signalling them.
cnd_signal() now returns invisibly.
cnd_signal() andcnd_abort() now acceptcharacter vectors to create typed conditions with several S3subclasses.
is_condition() is now properly exported.
Condition signallers such ascnd_signal() andabort() now accept a call depth ascallarguments. This allows plucking a call from further up the call stack(#30).
New helpercatch_cnd(). This is a small wrapperaroundtryCatch() that captures and returns any signalledcondition. It returnsNULL if none was signalled.
cnd_abort() now adds the correct S3 classes forerror conditions. This fixes error catching, for instance bytestthat::expect_error().
env_get_list() retrieves muliple bindings from anenvironment into a named list.
with_bindings() andscoped_bindings()establish temporary bindings in an environment.
is_namespace() is a snake case wrapper aroundisNamespace().
New functionsinherits_any(),inherits_all(), andinherits_only(). Theyallow testing for inheritance from multiple classes. The_any variant is equivalent tobase::inherits()but is more explicit about its behaviour.inherits_all()checks that all classes are present in order andinherits_only() checks that the class vectors areidentical.
Newfn_fmls<- andfn_fmls_names<-setters.
New function experimental functionchr_unserialise_unicode() for turning characters serialisedto unicode point form (e.g. <U+xxxx>) to UTF-8. Inaddition,as_utf8_character() now translates those as well.(@krlmlr)
expr_label() now supports quoted function definitioncalls (#275).
call_modify() andcall_standardise()gain an argument to specify an environment. The call definition islooked up in that environment when the call to modify or standardise isnot wrapped in a quosure.
is_symbol() gains aname argument tocheck that that the symbol name matches a string (#287).
Newrlang_box class. Its purpose is similar to theAsIs class frombase::I(), i.e. it protects avalue temporarily. However it does so by wrapping the value in a scalarlist. Usenew_box() to create a boxed value,is_box() to test for a boxed value, andunbox() to unbox it.new_box() andis_box() accept optional subclass.
The vector constructors such asnew_integer(),new_double_along() etc gain anames argument.In the case of the_along family it defaults to the namesof the input vector.
When nested quosures are evaluated witheval_tidy(),the.env pronoun now correctly refers to the currentquosure under evaluation (#174). Previously it would always refer to theenvironment of the outermost quosure.
as_pairlist() (part of the experimental API) nowsupportsNULL and objects of type pairlist (#397).
Fixed a performance bug inset_names() that caused afull copy of the vector names (
The rlang API is maturing and still in flux. However we have made aneffort to better communicate what parts are stable. We will notintroduce breaking changes for stable functions unless the payoff forthe change is worth the trouble. See?rlang::lifecycle forthe lifecycle status of exported functions.
The particle “lang” has been renamed to “call”:
lang() has been renamed tocall2().new_language() has ben renamed tonew_call().is_lang() has been renamed tois_call().We haven’t replaced theis_unary_lang() andis_binary_lang() because they are redundant with then argument ofis_call().lang_fn(),lang_name(),lang_args() etc aresoft-deprecated and renamed withcall_ prefix.In rlang 0.1 calls were called “language” objects in order to followthe R type nomenclature as returned bybase::typeof(). Wewanted to avoid adding to the confusion between S modes and R types.With hindsight we find it is better to use more meaningful typenames.
We now use the term “data mask” instead of “overscope”. We thinkdata mask is a more natural name in the context of R. We say that thatobjects from user data mask objects in the current environment. Thismakes reference to object masking in the search path which is due to thesame mechanism (in technical terms, lexical scoping with hierarchicallynested environments).
Following this new terminology, the new functionsas_data_mask() andnew_data_mask() replaceas_overscope() andnew_overscope().as_data_mask() has also a more consistent interface. Thesefunctions are only meant for developers of tidy evaluationinterfaces.
We no longer require a data mask (previously called overscope) tobe cleaned up after evaluation.overscope_clean() is thussoft-deprecated without replacement.
!! now binds tightly in order to match intuitiveparsing of tidy eval code, e.g. !! x > y is nowequivalent to(!! x) > y. A corollary of this new syntaxis that you now have to be explicit when you want to unquote the wholeexpression on the right of!!. For instance you have toexplicitly write!! (x > y) to unquotex > y rather than justx.
UQ(),UQS() and:= nowissue an error when called directly. The previous definitions causedsurprising results when the operators were invoked in wrong places(i.e. not in quasiquoted arguments).
The prefix form`!!`() is now an alias to!! rather thanUQE(). This makes it more inline with regular R syntax where operators are parsed as regular calls,e.g. a + b is parsed as`+`(a, b) and bothforms are completely equivalent. Also the prefix form`!!!`() is now equivalent to!!!.
UQE() is now deprecated in order to simplify thesyntax of quasiquotation. Please use!! get_expr(x)instead.
expr_interp() now returns a formula instead of aquosure when supplied a formula.
is_quosureish() andas_quosureish() aredeprecated. These functions assumed that quosures are formulas but thatis only an implementation detail.
new_cnd() is nowcnd() for consistencywith other constructors. Also,cnd_error(),cnd_warning() andcnd_message() are nowerror_cnd(),warning_cnd() andmessage_cnd() to follow our naming scheme according towhich the type of output is a suffix rather than a prefix.
is_node() now returnsTRUE for calls aswell andis_pairlist() does not returnTRUEforNULL objects. Useis_node_list() todetermine whether an object either of typepairlist orNULL. Note that all these functions are stillexperimental.
set_names() no longer automatically splices lists ofcharacter vectors as we are moving away from automatic splicingsemantics.
Calling the functional forms of unquote operators with the rlangnamespace qualifier is soft-deprecated.UQ() andUQS() are not function calls so it does not make sense tonamespace them. Supporting namespace qualifiers complicates theimplementation of unquotation and is misleading as to the nature ofunquoting (which are syntactic operators at quotation-time rather thanfunction calls at evaluation-time).
We are now questioningUQ() andUQS()as functional forms of!!. If!! and!!! were native R operators, they would parse to thefunctional calls`!!`() and`!!!`(). This isnow the preferred way to unquote with a function call rather than withthe operators. We haven’t decided yet whether we will deprecateUQ() andUQS() in the future. In any case werecommend using the new functional forms.
parse_quosure() andparse_quosures()are soft-deprecated in favour ofparse_quo() andparse_quos(). These new names are consistent with the rulethat abbreviated suffixes indicate the return type of a function. Inaddition the new functions require their callers to explicitly supply anenvironment for the quosures.
Usingf_rhs() andf_env() on quosuresis soft-deprecated. The fact that quosures are formulas is animplementation detail that might change in the future. Please usequo_get_expr() andquo_get_env()instead.
quo_expr() is soft-deprecated in favour ofquo_squash().quo_expr() was a misnomerbecause it implied that it was a mere expression acccessor for quosureswhereas it was really a lossy operation that squashed all nestedquosures.
With the renaming of thelang particle tocall, all these functions are soft-deprecated:lang(),is_lang(),lang_fn(),lang_name(),lang_args().
In addition,lang_head() andlang_tail()are soft-deprecated without replacement because these are low levelaccessors that are rarely needed.
as_overscope() is soft-deprecated in favour ofas_data_mask().
The node setters were renamed frommut_node_ prefixtonode_poke_. This change follows a new naming conventionin rlang where mutation is referred to as “poking”.
splice() is now in questioning stage as it is notneeded given the!!! operator works in functions takingdots withdots_list().
lgl_len(),int_len() etc have beensoft-deprecated and renamed withnew_ prefix,e.g. new_logical() andnew_integer(). This isfor consistency with other non-variadic object constructors.
ll() is now an alias tolist2(). Thisis consistent with the newcall2() constructor for calls.list2() andcall2() are versions oflist() andcall() that support splicing oflists with!!!.ll() remains around as ashorthand for users who like its conciseness.
Automatic splicing of lists in vector constructors(e.g. lgl(),chr(), etc) is nowsoft-deprecated. Please be explicit with the splicing operator!!!.
This is a maintenance release in anticipation of a forthcomingchange to R’s C API (useMARK_NOT_MUTABLE() instead ofSET_NAMED()).
New functionis_reference() to check whether twoobjects are one and the same.
eval_tidy() no longer maps over lists but returns themliterally. This behaviour is an overlook from past refactorings and wasnever documented.This hotfix release makes rlang compatible with the R 3.1 branch.
This release includes two important fixes for tidy evaluation:
Bare formulas are now evaluated in the correct environment intidyeval functions.
enquo() now works properly within compiledfunctions. Before this release, constants optimised by the bytecodecompiler couldn’t be enquoted.
Thenew_environment() constructor creates a child ofthe empty environment and takes an optional named list of data topopulate it. Compared toenv() andchild_env(), it is meant to create environments as datastructures rather than as part of a scope hierarchy.
Thenew_call() constructor creates calls out of acallable object (a function or an expression) and a pairlist ofarguments. It is useful to avoid costly internal coercions between listsand pairlists of arguments.
env_child()’s first argument is now.parent instead ofparent.
mut_ setters likemut_attrs() andenvironment helpers likeenv_bind() andenv_unbind() now return their (modified) input invisibly.This follows the tidyverse convention that functions called primarilyfor their side effects should return their input invisibly.
is_pairlist() now returnsTRUE forNULL. We addedis_node() to test for actualpairlist nodes. In other words,is_pairlist() tests for thedata structure whileis_node() tests for the type.
env() andenv_child() can now getarguments whose names start with.. Prior to this fix,these arguments were partial-matching onenv_bind()’s.env argument.
The internalreplace_na() symbol was renamed toavoid a collision with an exported function in tidyverse. This solves anissue occurring in old versions of R prior to 3.3.2 (#133).
Initial release.