Setting attributes to objects with pipes

Viewed 361

I use attributes extensively I like to use pipes to set them up.

I use a lot rlang::set_attrs, but it was deprecated as of rlang 0.3.0.

However, there was no explanation of this deprecation (never mentioned on NEWS.md), and the structure of this function seems really harmless to me:

> rlang::set_attrs
function (.x, ...) 
{
    warn_deprecated("`set_attrs()` is deprecated as of rlang 0.3.0")
    if (!is_copyable(.x)) {
        abort("`.x` is uncopyable: use `mut_attrs()` to change attributes in place")
    }
    set_attrs_impl(.x, ...)
}
<bytecode: 0x000001d759d6ecd8>
<environment: namespace:rlang>

> rlang:::set_attrs_impl
function (.x, ...) 
{
    attrs <- dots_list(...)
    if (identical(attrs, set_attrs_null)) {
        attributes(.x) <- NULL
    }
    else {
        attributes(.x) <- c(attributes(.x), attrs)
    }
    .x
}
<bytecode: 0x000001d75d8f2128>
<environment: namespace:rlang>

This seems to be the same thing as setting them in another line, with attr().

I know about data.table::setattr, but it has not exactly the same behavior and seems less fit for piping.

In the end, should I avoid using rlang::set_attrs? If yes, what should I avoid reproducing in a custom function that would have the same purpose?

1 Answers

This answer may not be fulfulling for all, but it's some research (for perspective).

set_attrs was first soft-deprecated in Sept 2018, in a859be5. If you look at that commit, all of the uses of set_attrs were inline-replaced something like one of the below:

-  set_attrs(dict, class = class(x))
+  structure(dict, class = class(x))

or

-  x <- set_attrs(x, NULL)
-  x <- set_attrs(x, srcref = srcref)
+  attributes(x) <- NULL
+  x <- structure(x, srcref = srcref)

I think the rlang developers (perhaps even @lionel-henry who crafted that commit) will weigh in with rationale, but ... I suspect it was that the function wasn't adding a huge amount of convenience (very subjective, I admit).


While not awesome, one inline replacement could use `attr<-`:

library(dplyr)

mtcars %>%
  identical(rlang::set_attrs(mtcars, nm = "foo"))
# [1] FALSE

mtcars %>%
  `attr<-`(., "nm", "foo") %>%
  identical(rlang::set_attrs(mtcars, nm = "foo"))
# [1] TRUE
Related