英文:
How does `bquote` handle the dimensions of terms wrapped in `.()`?
问题
R在expr表达式中知道X是一个矩阵,尽管在函数调用的上下文中X被强制转换为向量。
英文:
I am confused about how bquote handles multidimensional terms (e.g., a matrix)
wrapped in .().
Suppose I have the following X matrix.
# Set a seed exact draws.
set.seed(2023)
# Create a matrix.
X <- matrix(sample(1:100, 9), nrow = 3, ncol = 3)
X
# [,1] [,2] [,3]
# [1,] 80 26 29
# [2,] 47 44 49
# [3,] 72 65 81
Wrapping X in .() does what I expect, i.e., it retains its dimensions.
# Wrap `X` in `.()`.
bquote(.(X))
# [,1] [,2] [,3]
# [1,] 80 26 29
# [2,] 47 44 49
# [3,] 72 65 81
However, in the context of a function call, it seems that X is coerced to a
vector. Despite this, R somehow still knows that X is a matrix, as seen in the output of the apply call below.
# Apply a function over rows.
output <- apply(X = X, MARGIN = 1, FUN = function(row) mean(row))
output
# [1] 45.00000 46.66667 72.66667
# Create an expression to apply a function over rows later.
expr <- bquote(apply(X = .(X), MARGIN = 1, FUN = function(row) mean(row)))
expr
# apply(X = c(80L, 47L, 72L, 26L, 44L, 65L, 29L, 49L, 81L), MARGIN = 1,
# FUN = function(row) mean(row))
# Not necessary, but remove `X`.
rm(X, envir = .GlobalEnv)
# Evaluate the expression and compare it with the previous output.
eval(expr) == output
# [1] TRUE TRUE TRUE
How does R know that X is a matrix in the expr expression above?
答案1
得分: 1
"bquote" 在这里不相关。一个更简单的示例:
> expr <- call("is.matrix", matrix(1:4, 2L, 2L))
> expr[[2L]]
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
> eval(expr)
# [1] TRUE
> print(expr)
# is.matrix(1:4)
调用的参数确实是一个矩阵,但 print.default 在去除属性时将其解析。deparse 做了正确的事情:
> writeLines(deparse(expr))
# is.matrix(structure(1:4, dim = c(2L, 2L)))
原因是 deparse 默认使用了 "showAttributes" 选项:
> (ctrl <- eval(formals(deparse)[["control"]]))
# [1] "keepNA" "keepInteger" "niceNames" "showAttributes"
这个字符向量由 .deparseOpts 转换为一个整数,其位表示相应选项的开启或关闭:
> .deparseOpts(ctrl)
# [1] 1093
在 R 的源代码中,头文件 Defn.h 定义了映射关系:
/* deparse option bits: change do_dump if more are added */
#define KEEPINTEGER 1
#define QUOTEEXPRESSIONS 2
#define SHOWATTRIBUTES 4
#define USESOURCE 8
#define WARNINCOMPLETE 16
#define DELAYPROMISES 32
#define KEEPNA 64
#define S_COMPAT 128
#define HEXNUMERIC 256
#define DIGITS17 512
#define NICE_NAMES 1024
/* common combinations of the above */
#define SIMPLEDEPARSE 0
#define DEFAULTDEPARSE 1089 /* KEEPINTEGER | KEEPNA | NICE_NAMES, used for calls */
#define FORSOURCING 95 /* not DELAYPROMISES, used in edit.c */
如果你在 print.c 中查找(在 PrintLanguage 函数的主体中),你会发现 print.default 为语言对象使用了 DEFAULTDEPARSE 选项。它关闭了 SHOWATTRIBUTES 位,用户没有选项可以将其打开。
嗯,我刚刚在 R-devel 邮件列表中询问了(参见 此处)是否应将 DEFAULTDEPARSE 更改为 1093 以匹配 R 层级的默认设置。
英文:
bquote is irrelevant here. A simpler example:
> expr <- call("is.matrix", matrix(1:4, 2L, 2L))
> expr[[2L]]
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
> eval(expr)
# [1] TRUE
> print(expr)
# is.matrix(1:4)
The argument of the call is a matrix, but print.default deparses it without attributes. deparse does the right thing:
> writeLines(deparse(expr))
# is.matrix(structure(1:4, dim = c(2L, 2L)))
The reason is that deparse uses the "showAttributes" option by default:
> (ctrl <- eval(formals(deparse)[["control"]]))
# [1] "keepNA" "keepInteger" "niceNames" "showAttributes"
This character vector is converted by .deparseOpts to an integer whose bits indicate whether the respective options are turned on or off:
> .deparseOpts(ctrl)
# [1] 1093
The header file Defn.h in R's sources defines the mapping:
/* deparse option bits: change do_dump if more are added */
#define KEEPINTEGER 1
#define QUOTEEXPRESSIONS 2
#define SHOWATTRIBUTES 4
#define USESOURCE 8
#define WARNINCOMPLETE 16
#define DELAYPROMISES 32
#define KEEPNA 64
#define S_COMPAT 128
#define HEXNUMERIC 256
#define DIGITS17 512
#define NICE_NAMES 1024
/* common combinations of the above */
#define SIMPLEDEPARSE 0
#define DEFAULTDEPARSE 1089 /* KEEPINTEGER | KEEPNA | NICE_NAMES, used for calls */
#define FORSOURCING 95 /* not DELAYPROMISES, used in edit.c */
If you dig around in print.c, then you'll find (in the body of function PrintLanguage) that print.default uses the DEFAULTDEPARSE option for language objects. It has the SHOWATTRIBUTES bit turned off, and there is no option for the user to turn it on.
Well, I've just asked in the R-devel mailing list (i.e., see here) if DEFAULTDEPARSE should be changed to 1093 to match the R level default.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论