在 R 中,如何通过自定义打印函数可靠地打印对象的名称?
In R, how can I print the name of an object reliably from a custom print function?
我在 R 中创建了一个 class,并且正在尝试为该 class 创建一个打印函数。我希望打印函数打印传递给打印函数的对象的名称。使用标准 deparse(substitute())
我可以获得变量的名称,这在我直接调用 print()
函数时有效。但是当我只是 运行 来自 R Studio 的变量时它不起作用。它显然是在调用我的打印功能。但是有一些间接导致它丢失变量名。这是一个例子:
# Define class 'myobj'
myobj <- function(val) {
obj <- structure(list(), class = c("myobj", "list"))
obj$value = val
return(obj)
}
# Write custom print function for 'myobj' class
#' @export
print.myobj <- function(x, ...) {
nm <- deparse1(substitute(x, env = environment()))
cat(paste0("My object name: ", nm, "\n"))
cat(paste0("My object value: ", x$value, "\n"))
invisible(x)
}
myInstance <- myobj(123)
# Prints name and value.
print(myInstance)
#> My object name: myInstance
#> My object value: 123
# Prints value, but name is local variable 'x'.
myInstance
#> My object name: x
#> My object value: 123
当您直接 运行 变量时,它似乎嵌套在另一个框架或环境中,因此 deparse(substitute())
无法正常工作。
如何让我的打印函数可靠地打印变量的名称,无论它是如何调用的?
自动打印 documentation 表示它由 print.c
处理。
这个函数看起来像这样。
static void PrintObjectS3(SEXP s, R_PrintData *data)
{
/*
Bind value to a variable in a local environment, similar to
a local({ x <- <value>; print(x) }) call. This avoids
problems in previous approaches with value duplication and
evaluating the value, which might be a call object.
*/
SEXP xsym = install("x");
SEXP mask = PROTECT(NewEnvironment(R_NilValue, R_NilValue, data->env));
defineVar(xsym, s, mask);
/* Forward user-supplied arguments to print() */
SEXP fun = PROTECT(findFun(install("print"), R_BaseNamespace));
SEXP args = PROTECT(cons(xsym, data->callArgs));
SEXP call = PROTECT(lcons(fun, args));
eval(call, mask);
defineVar(xsym, R_NilValue, mask); /* To eliminate reference to s */
UNPROTECT(4); /* mask, fun, args, call */
}
注意上面写着
similar to a local({ x <- <value>; print(x) })
所以自动打印不会直接调用print(myInstance)
。它用符号 x
做事,所以我认为以你想要的方式获取变量名是不可能的。
通过查看 traceback
.
可以看出差异
print.myobj <- function(x, ...) {
stop()
}
print(myInstance)
#> (Traceback)
#> 3. stop()
#> 2. print.myobj(myInstance)
#> 1. print(myInstance)
myInstance
#> (Traceback)
#> 3. stop()
#> 2. print.myobj(x)
#> 1. (function (x, ...)
#> UseMethod("print"))(x)
我在 R 中创建了一个 class,并且正在尝试为该 class 创建一个打印函数。我希望打印函数打印传递给打印函数的对象的名称。使用标准 deparse(substitute())
我可以获得变量的名称,这在我直接调用 print()
函数时有效。但是当我只是 运行 来自 R Studio 的变量时它不起作用。它显然是在调用我的打印功能。但是有一些间接导致它丢失变量名。这是一个例子:
# Define class 'myobj'
myobj <- function(val) {
obj <- structure(list(), class = c("myobj", "list"))
obj$value = val
return(obj)
}
# Write custom print function for 'myobj' class
#' @export
print.myobj <- function(x, ...) {
nm <- deparse1(substitute(x, env = environment()))
cat(paste0("My object name: ", nm, "\n"))
cat(paste0("My object value: ", x$value, "\n"))
invisible(x)
}
myInstance <- myobj(123)
# Prints name and value.
print(myInstance)
#> My object name: myInstance
#> My object value: 123
# Prints value, but name is local variable 'x'.
myInstance
#> My object name: x
#> My object value: 123
当您直接 运行 变量时,它似乎嵌套在另一个框架或环境中,因此 deparse(substitute())
无法正常工作。
如何让我的打印函数可靠地打印变量的名称,无论它是如何调用的?
自动打印 documentation 表示它由 print.c
处理。
这个函数看起来像这样。
static void PrintObjectS3(SEXP s, R_PrintData *data)
{
/*
Bind value to a variable in a local environment, similar to
a local({ x <- <value>; print(x) }) call. This avoids
problems in previous approaches with value duplication and
evaluating the value, which might be a call object.
*/
SEXP xsym = install("x");
SEXP mask = PROTECT(NewEnvironment(R_NilValue, R_NilValue, data->env));
defineVar(xsym, s, mask);
/* Forward user-supplied arguments to print() */
SEXP fun = PROTECT(findFun(install("print"), R_BaseNamespace));
SEXP args = PROTECT(cons(xsym, data->callArgs));
SEXP call = PROTECT(lcons(fun, args));
eval(call, mask);
defineVar(xsym, R_NilValue, mask); /* To eliminate reference to s */
UNPROTECT(4); /* mask, fun, args, call */
}
注意上面写着
similar to a
local({ x <- <value>; print(x) })
所以自动打印不会直接调用print(myInstance)
。它用符号 x
做事,所以我认为以你想要的方式获取变量名是不可能的。
通过查看 traceback
.
print.myobj <- function(x, ...) {
stop()
}
print(myInstance)
#> (Traceback)
#> 3. stop()
#> 2. print.myobj(myInstance)
#> 1. print(myInstance)
myInstance
#> (Traceback)
#> 3. stop()
#> 2. print.myobj(x)
#> 1. (function (x, ...)
#> UseMethod("print"))(x)