简体   繁体   English

R中的替换和引用有什么区别

[英]What's the difference between substitute and quote in R

In the official docs, it says:在官方文档中,它说:

substitute returns the parse tree for the (unevaluated) expression expr, substituting any variables bound in env.替换返回(未计算的)表达式 expr 的解析树,替换 env 中绑定的任何变量。

quote simply returns its argument. quote 只是返回它的参数。 The argument is not evaluated and can be any R expression.参数不被计算,可以是任何 R 表达式。

But when I try:但是当我尝试:

> x <- 1
> substitute(x)
x
> quote(x)
x

It looks like both quote and substitute returns the expression that's passed as argument to them.看起来quotesubstitute返回作为参数传递给它们的表达式。

So my question is, what's the difference between substitute and quote , and what does it mean to "substituting any variables bound in env"?所以我的问题是, substitutequote之间有什么区别,“替换 env 中绑定的任何变量”是什么意思?

Here's an example that may help you to easily see the difference between quote() and substitute() , in one of the settings (processing function arguments) where substitute() is most commonly used:下面是一个可以帮助你轻松地看到之间的差异的例子quote()substitute()在设置一个(处理函数参数),其中substitute()是最常用的:

f <- function(argX) {
   list(quote(argX), 
        substitute(argX), 
        argX)
}
    
suppliedArgX <- 100
f(argX = suppliedArgX)
# [[1]]
# argX
# 
# [[2]]
# suppliedArgX
# 
# [[3]]
# [1] 100

R has lazy evaluation, so the identity of a variable name token is a little less clear than in other languages. R 具有惰性求值,因此变量名标记的标识比其他语言要少一些。 This is used in libraries like dplyr where you can write, for instance:这用于像dplyr这样的库中,您可以在其中编写,例如:

summarise(mtcars, total_cyl = sum(cyl))

We can ask what each of these tokens means: summarise and sum are defined functions, mtcars is a defined data frame, total_cyl is a keyword argument for the function summarise .我们可以问一问每个的这些标记手段: summarisesum都定义函数, mtcars是一个定义的数据帧, total_cyl是功能的关键字参数summarise But what is cyl ?但什么是cyl

> cyl
Error: object 'cyl' not found

It isn't anything!不是什么! Well, not yet.嗯,还没有。 R doesn't evaluate it right away, but treats it as an expression to be parsed later with some parse tree that is different than the global environment your command line is working in, specifically one where the columns of mtcars are defined. R 不会立即对其进行评估,而是将其视为一个表达式,稍后会使用一些不同于命令行工作的全局环境的解析树进行解析,特别是在其中定义了mtcars列的mtcars Somewhere in the guts of dplyr, something like this is happening:在 dplyr 的某个地方,正在发生这样的事情:

> substitute(cyl, mtcars)
[1] 6 6 4 6 8 ...

Suddenly cyl means something.突然cyl意味着什么。 That's what substitute is for.这就是substitute的作用。

So what is quote for?那么quote有什么用呢? Well sometimes you want your lazily-evaluated expression to be represented somewhere else before it's evaluated , ie you want to display the actual code you're writing without any (or only some) values substituted.好吧,有时您希望延迟计算的表达式在计算之前在其他地方表示,即您想显示您正在编写的实际代码,而无需替换任何(或仅部分)值。 The docs you quoted explain this is common for "informative labels for data sets and plots".您引用的文档解释了这对于“数据集和绘图的信息标签”很常见。

So, for example, you could create a quoted expression, and then both print the unevaluated expression in your chart to show how you calculated and actually calculate with the expression.因此,例如,您可以创建一个带引号的表达式,然后在图表中打印未计算的表达式,以显示您如何计算和实际使用该表达式进行计算

expr <- quote(x + y)
print(expr) # x + y
eval(expr, list(x = 1, y = 2)) # 3

Note that substitute can do this expression trick also while giving you the option to parse only part of it.请注意, substitute也可以执行此表达式技巧,同时为您提供仅解析其中一部分的选项。 So its features are a superset of quote .所以它的特征是quote的超集。

expr <- substitute(x + y, list(x = 1))
print(expr) # 1 + y
eval(expr, list(y = 2)) # 3

Maybe this section of the documentation will help somewhat:也许文档的这一部分会有所帮助:

Substitution takes place by examining each component of the parse tree as follows: If it is not a bound symbol in env, it is unchanged.通过如下检查分析树的每个组件来进行替换:如果它不是 env 中的绑定符号,则它保持不变。 If it is a promise object, ie, a formal argument to a function or explicitly created using delayedAssign(), the expression slot of the promise replaces the symbol.如果它是一个promise 对象,即函数的正式参数或使用delayedAssign() 显式创建,promise 的表达式槽将替换符号。 If it is an ordinary variable, its value is substituted, unless env is .GlobalEnv in which case the symbol is left unchanged.如果是普通变量,则替换其值,除非 env 是 .GlobalEnv 在这种情况下,符号保持不变。

Note the final bit, and consider this example:注意最后一点,并考虑这个例子:

e <- new.env()
assign(x = "a",value = 1,envir = e)
> substitute(a,env = e)
[1] 1

Compare that with:比较一下:

> quote(a)
a

So there are two basic situations when the substitution will occur: when we're using it on an argument of a function, and when env is some environment other than .GlobalEnv .所以,有些时候会发生替代两种基本情况:当我们使用它的函数的参数,当env其他一些环境.GlobalEnv So that's why you particular example was confusing.所以这就是为什么你的特定例子令人困惑。

For another comparison with quote , consider modifying the myplot function in the examples section to be:要与quote进行另一个比较,请考虑将示例部分中的myplot函数修改为:

myplot <- function(x, y)
    plot(x, y, xlab = deparse(quote(x)),
             ylab = deparse(quote(y)))

and you'll see that quote really doesn't do any substitution.你会看到quote真的没有做任何替换。

Regarding your question why GlobalEnv is treated as an exception for substitute, it is just a heritage of S. From The R language definition ( https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Substitutions ):关于您的问题,为什么 GlobalEnv 被视为替代品的例外,它只是 S 的遗产。来自 R 语言定义( https://cran.r-project.org/doc/manuals/r-release/R-lang .html#Substitutions ):

The special exception for substituting at the top level is admittedly peculiar.在顶层替换的特殊例外无疑是特殊的。 It has been inherited from S and the rationale is most likely that there is no control over which variables might be bound at that level so that it would be better to just make substitute act as quote.它是从 S 继承而来的,其基本原理很可能是无法控制在该级别上可能绑定哪些变量,因此最好仅将替代行为作为引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM