Rlang::f_rhs and lazyeval::f_rhs

Both the lazyeval and rlang package contain f_rhs and f_lhs functions (lazyeval and rlang). They even have the same docs associated with them.

However (as far as I can see), neither package depends on the other. Given the fact that both are tidyverse packages and share a lot of contributors, I assume there's something going on here/some way that code is being shared that I've missed.

Can anyone here point me in the right direction? A blog post or a textbook that might help me understand what's going on?

^^ lionel, who's most definitely among said contributors, actually addresses this question in broader terms here:

They're actually not. rlang, however, is part of r-lib. I'm excerpting from an answer here to a different question (since the rest of it isn't particularly relevant) wherein I describe r-lib in further detail.

rlang is under active development and used for non-standard evaluation (NSE) in tidyverse packages, e.g. dplyr. You can learn more about that in the Programming with dplyr vignette:

It's also used in the in-progress second edition of Hadley's Advanced R book (below links to the section on metaprogramming):

I don't think that's necessarily true. As you've pointed out, neither depends on the other and sometimes when things are reworked, functionality from one package may migrate to another.


Thanks Mara - this is really informative.

This is really interesting. I was aware of r-lib but had always assumed it was at least tidyverse-adjacent (since its packages often pop up in tidyverse/tidyverse-friendly packages). Your answer helps a lot.

This looks great. So as I understand it using tidyeval with rlang in packages/DSLs is preferred over lazyeval now?

The tidyverse is a set of packages designed for interactive data analysis. r-lib packages are more developer-oriented utilities.

The r-lib organisation (in GitHub parlance, it is an organisation) is a collection of fundamental infrastructure packages like R6, xml2, fs, and testthat. The packages that are part of that organization are ones we see it as a piece of important infrastructure for the R community.

The team I work on at RStudio is something to the effect of the tidyverse/r-lib team. That is not to say that all of the creators/authors/maintainers of the packages work at RStudio (they don't). This is especially true of r-lib. (You can peruse the GitHub organization, members, and packages, which will show this better than I could describe.)

If you're asking about the use of NSE in the tidyverse, then yes. The links at the bottom of the vignette you linked to above go to the first edition of Advanced R. The second edition uses rlang and tidy eval.

tidyverse packages either have or are moving to support tidy eval, e.g. ggplot2 now supports tidy evaluation, as part of our making this consistent throughout the tidyverse

1 Like

lazyeval is the first attempt at making NSE suitable for programming rather than just interactive use. It had some conceptual issues and was relying too much on R internals. It was not practical because developers had to write two versions of each function, one SE and one NSE. Passing in variable names or expressions required painful manual interpolation. Variable number of arguments had to be passed through an additional .dots. This all lead to a lot boilerplate.

Given all these shortcomings, @hadley started working on the ancestor of tidyeval with the insight that quasiquotation would make it possible to program directly on NSE functions. However that early version of tidyeval was based on formulas rather than quosures. This is why the latest update of lazyeval includes formula accessors and setters to make it easier to program with them.

When I started working on rlang the primary goal was to finish the theory and implementation of tidyeval but also to provide a consistent API for dealing with R primitives and data structures (still a WIP, please only rely on the parts that are marked stable in ?rlang::lifecycle). Lots of lazyeval were relevant for this purpose and in fact rlang development was started on top of lazyeval, which is still included in its commit history. That is why it contains the formula API even though formulas are no longer important for tidyeval.


Thanks both of you for your comprehensive answers. This helps a lot.

1 Like