New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infix attr accessor #69

Closed
hadley opened this Issue Apr 28, 2015 · 7 comments

Comments

Projects
None yet
3 participants
@hadley
Member

hadley commented Apr 28, 2015

Maybe purrr would be a good place for:

`%@%` <- function(x, name) attr(x, name)

Need to think about if this should be S3 generic or not, and need to check if this works as is for S4.

@lionel-

This comment has been minimized.

Member

lionel- commented Apr 28, 2015

I've always been frustrated that @ does not work as an attribute accessor... Especially since Kevin Ushey mentioned on twitter that S4 slots are actually attributes.

I suppose it would be highly inappropriate to force the matter and export a redefinition?

`@` <- function(x, slot) {
  slot <- as.character(substitute(slot))

  if (isS4(x)) {
    env <- new.env(parent = parent.frame())
    env$`@` <- base::`@`
    eval(call("@", x, slot), envir = env)
  } else {
    attr(x, slot)
  }
}

mtcars@names
@hadley

This comment has been minimized.

Member

hadley commented Apr 28, 2015

Yeah, we can't override existing functions, so I think %@% is the best we can do. It might be worth trying to push upstream to R core though.

@npjc

This comment has been minimized.

npjc commented May 10, 2015

would this follow then?

x %@% "foo" <- "bar"    # attr(x,"foo") <- "bar"     // x.attr("foo") = "bar";

OR use %<@% analogous to the %<>% relationship %>%

if so then what of

attributes(x) <- list(mycomment = "really special", foo = 3:2,bar = paste(1:6))
x %<@% list(mycomment = "really special", foo = 3:2,bar = paste(1:6))

then you need an .append = TRUE or such...

@lionel-

This comment has been minimized.

Member

lionel- commented May 10, 2015

The first one works:

`%@%` <- attr
`%@%<-` <- `attr<-`

mtcars %@% "names"
mtcars %@% "names" <- 1:11

The idea of overloading these operators to work with lists seems interesting.

`%@%` <- function(x, slots) {
  if (length(slots) > 1) {
    attributes(x)[slots]
  } else {
    attr(x, slots)
  }
}

`%@%<-` <- function(x, slots, value) {
  if (length(slots) > 1) {
    attributes(x)[slots] <- value
    x
  } else {
    attr(x, slots) <- value
  }
}

mat <- as.matrix(mtcars)
mat %@% c("dimnames", "dim")
mat %@% c("dimnames", "dim") <- list(NULL, c(2, 16, 11))

But it's not good to have the output type change as a function of the number of slots requested. So we'd have to choose one of those two behaviours. The most useful is the list of attributes accessor probably, and we can still hope that R core will enable single attribute lookup with @ in the future :)

@lionel-

This comment has been minimized.

Member

lionel- commented May 10, 2015

it's not good to have the output type change as a function of the number of slots requested.

One possibility is to make the behaviour depend on whether the slot is a vector or a list. But the syntax becomes kind of heavy then

mat %@% list("dimnames", "dim") <- list(NULL, c(2, 16, 11))
@hadley

This comment has been minimized.

Member

hadley commented Sep 24, 2015

I'd rather keep it simple and stick with just getting of single values.

@hadley

This comment has been minimized.

Member

hadley commented Nov 11, 2015

Closed in 97ddec7

@hadley hadley closed this Nov 11, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment