定义`(<-`运算符时获取x的名称

时间:2018-07-09 13:12:03

标签: r assignment-operator

我想定义(<-并访问左侧参数的名称:

*<-函数在内部使用中间'*tmp*'变量。是否仍有可能获得x的名称?

`(<-` <- function(x,value){
  print(deparse(substitute(value)))
  print(deparse(substitute(x)))
  print(match.call())
  value
}

foo <- 0
(foo) <- 3
# [1] "3"
# [1] "*tmp*"
# `(<-`(x = `*tmp*`, value = 3)# [1] "3"

我想从函数内部获取“ foo”。

我试图通过使用tracemem来破解它,即在函数内部调用sapply(ls(envir = parent.frame()),tracemem)tracemem(x),但调用地址为foo*temp*和{ {1}}都是不同的。

2 个答案:

答案 0 :(得分:3)

尽管我不了解自己所做的一切,但我还是将其破解了。

我注意到pryr::address给出的结果与tracemem不同,并尝试了一下(我不得不深入研究代码以使用pryr:::address2,因为pryr::address并没有有一个环境参数)。

然后我注意到,将tracemem上的xpryr:::address2上的其余对象混合的结果存在一个匹配项(在基本重新格式化之后):

`(<-` <- function(x,value){
  pf <- parent.frame()
  all_addresses       <- sapply(ls(pf), pryr:::address2, pf)
  all_addresses       <- all_addresses[names(all_addresses) != "*tmp*"]
  all_addresses_short <- gsub("(^|<)[0x]*(.*?)(>|$)","\\2",all_addresses)

  x_address       <- tracemem(x)
  x_address_short <- tolower(gsub("(^|<)[0x]*(.*?)(>|$)","\\2",x_address))

  ind    <- match(x_address_short, all_addresses_short)
  x_name <- names(all_addresses)[ind]

  message("all_addresses, using pryr::address2")
  print(all_addresses)
  print(all_addresses_short)

  message("x_address, using tracemem")
  print(x_address)
  print(x_address_short)

  message("x_name, matching substrings")
  print(x_name)

  value
}

gsub调用中使用的正则表达式试图说明我们在不同系统上获得的地址格式,我不确定100%是否确定它是通用的。

输出:

foo <- 1
bar <- 2
(foo) <- foo

# all_addresses, using pryr::address2
# (<-          bar          foo 
# "0x1433df50" "0x14937678" "0x14937708" 
# (<-        bar        foo 
# "1433df50" "14937678" "14937708" 
# x_address, using tracemem
# [1] "<0000000014937708>"
# [1] "14937708"
# x_name, matching substrings
# [1] "foo"

如果x不是变量名,则会中断,例如:

foo <- iris
(foo$species) <- 3

我们可以假设,如果找不到该地址,则x是一个列表项,然后在parent.frame中递归地在所有列表项的地址中查找其地址,但我认为对于今天来说,这已经足够丑陋了。

答案 1 :(得分:2)

1)(如果您愿意更改它以使通话为:

fooify[foo] <- 99

然后我们可以这样做,其中foo不需要事先存在:

fooify <- structure(NA, class = "fooify")
"[<-.fooify" <- function(x, var, value) {
  print(deparse(substitute(var)))
  eval.parent(substitute(var <- value))
  x
}

# test

if (exists("foo")) rm(foo)
fooify[foo] <- 99
## [1] "foo"  <-- this comes from the print statement
foo
## [1] 99

2):= 如果可以使用:=,则:

`:=` <- function(lhs, rhs) {
  print(deparse(substitute(lhs)))
  eval.parent(substitute(lhs <- rhs))
}

# test
if (exists("foo")) rm(foo)
foo := 99
## [1] foo   <-- this comes from print statement
foo
## [1] 99