Skip to content
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
Closed

Infix attr accessor #69

hadley opened this issue Apr 28, 2015 · 7 comments

Comments

@hadley
Copy link
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-
Copy link
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
Copy link
Member Author

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
Copy link

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-
Copy link
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-
Copy link
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
Copy link
Member Author

hadley commented Sep 24, 2015

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

@hadley
Copy link
Member Author

hadley commented Nov 11, 2015

Closed in 97ddec7

@hadley hadley closed this as completed Nov 11, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants