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. 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.
看起来引号和替换都返回作为参数传递给它们的表达式。
So my question is, what's the difference between substitute
and quote
, and what does it mean to "substituting any variables bound in env"?
我的问题是,代换和引用的区别是什么,它是什么意思"替换env中的任何变量"?
4 个解决方案
#1
12
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()和replace()之间的区别,在其中的一个设置(处理函数参数)中,替代()是最常用的:
f <- function(argX) {
list(quote(argX), substitute(argX), argX)
}
suppliedArgX <- 100
f(argX = suppliedArgX)
# [[1]]
# argX
#
# [[2]]
# suppliedArgX
#
# [[3]]
# [1] 100
#2
5
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. If it is a promise object, i.e., a formal argument to a function or explicitly created using delayedAssign(), the expression slot of the promise replaces the symbol. If it is an ordinary variable, its value is substituted, unless env is .GlobalEnv in which case the symbol is left unchanged.
替换通过如下检查解析树的每个组件进行:如果它不是env中的绑定符号,那么它是不变的。如果它是一个承诺对象,也就是。,一个函数的正式参数或使用delayedAssign()显式创建的,承诺的表达式槽将替换符号。如果它是一个普通变量,它的值被替换,除非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
. So that's why you particular example was confusing.
有两种基本情况会发生替换:当我们在函数的参数上使用它时,以及当env是。globalenv以外的环境时。这就是为什么你的例子让人困惑。
For another comparison with quote
, consider modifying the myplot
function in the examples section to be:
对于与引用的另一个比较,请考虑修改示例部分中的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.
你会发现这个引语并没有做任何替换。
#3
2
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被视为替代品的一个例外,它只是R语言定义中s的遗产(https://cran.r-project.org/doc/manuals/r-release/R-lang.html#替换):
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继承而来的,其基本原理很可能是没有控制哪个变量可以在那个水平上被约束,所以最好让代用品作为引用。
#4
1
R has lazy evaluation, so the identity of a variable name token is a little less clear than in other languages. This is used in libraries like dplyr
where you can write, for instance:
R有延迟的计算,所以变量名令牌的标识比其他语言的标识更不清晰。这在像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
. But what is cyl
?
我们可以问每一个令牌是什么意思:summary和sum都是定义好的函数,mtcars是定义好的数据帧,total_cyl是函数summary的关键字参数。但共青团是什么?
> 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. Somewhere in the guts of dplyr, something like this is happening:
它不是任何东西!哦,还没有。R不会马上对它进行评估,而是将它作为一个表达式,稍后使用与命令行所处的全局环境不同的解析树进行解析,特别是在定义了mtcars列的全局环境中。在dplyr的内部某处,类似的事情正在发生:
> substitute(cyl, mtcars)
[1] 6 6 4 6 8 ...
Suddenly cyl
means something. That's what substitute
is for.
突然共青团意味着什么。这就是代用品。
So what is quote
for? Well sometimes you want your lazily-evaluated expression to be represented somewhere else before it's evaluated, i.e. 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. So its features are a superset of quote
.
注意,代用也可以执行这个表达式技巧,同时允许您只解析它的一部分。所以它的特征是一个超集。
expr <- substitute(x + y, list(x = 1))
print(expr) # 1 + y
eval(expr, list(y = 2)) # 3
#1
12
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()和replace()之间的区别,在其中的一个设置(处理函数参数)中,替代()是最常用的:
f <- function(argX) {
list(quote(argX), substitute(argX), argX)
}
suppliedArgX <- 100
f(argX = suppliedArgX)
# [[1]]
# argX
#
# [[2]]
# suppliedArgX
#
# [[3]]
# [1] 100
#2
5
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. If it is a promise object, i.e., a formal argument to a function or explicitly created using delayedAssign(), the expression slot of the promise replaces the symbol. If it is an ordinary variable, its value is substituted, unless env is .GlobalEnv in which case the symbol is left unchanged.
替换通过如下检查解析树的每个组件进行:如果它不是env中的绑定符号,那么它是不变的。如果它是一个承诺对象,也就是。,一个函数的正式参数或使用delayedAssign()显式创建的,承诺的表达式槽将替换符号。如果它是一个普通变量,它的值被替换,除非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
. So that's why you particular example was confusing.
有两种基本情况会发生替换:当我们在函数的参数上使用它时,以及当env是。globalenv以外的环境时。这就是为什么你的例子让人困惑。
For another comparison with quote
, consider modifying the myplot
function in the examples section to be:
对于与引用的另一个比较,请考虑修改示例部分中的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.
你会发现这个引语并没有做任何替换。
#3
2
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被视为替代品的一个例外,它只是R语言定义中s的遗产(https://cran.r-project.org/doc/manuals/r-release/R-lang.html#替换):
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继承而来的,其基本原理很可能是没有控制哪个变量可以在那个水平上被约束,所以最好让代用品作为引用。
#4
1
R has lazy evaluation, so the identity of a variable name token is a little less clear than in other languages. This is used in libraries like dplyr
where you can write, for instance:
R有延迟的计算,所以变量名令牌的标识比其他语言的标识更不清晰。这在像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
. But what is cyl
?
我们可以问每一个令牌是什么意思:summary和sum都是定义好的函数,mtcars是定义好的数据帧,total_cyl是函数summary的关键字参数。但共青团是什么?
> 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. Somewhere in the guts of dplyr, something like this is happening:
它不是任何东西!哦,还没有。R不会马上对它进行评估,而是将它作为一个表达式,稍后使用与命令行所处的全局环境不同的解析树进行解析,特别是在定义了mtcars列的全局环境中。在dplyr的内部某处,类似的事情正在发生:
> substitute(cyl, mtcars)
[1] 6 6 4 6 8 ...
Suddenly cyl
means something. That's what substitute
is for.
突然共青团意味着什么。这就是代用品。
So what is quote
for? Well sometimes you want your lazily-evaluated expression to be represented somewhere else before it's evaluated, i.e. 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. So its features are a superset of quote
.
注意,代用也可以执行这个表达式技巧,同时允许您只解析它的一部分。所以它的特征是一个超集。
expr <- substitute(x + y, list(x = 1))
print(expr) # 1 + y
eval(expr, list(y = 2)) # 3