[R]在dplyr基础上编写函数-(2)substitute和quote

关于这两个函数,官方是这么定义的:

substitute returns the parse tree for the (unevaluated) expression expr, substituting any variables bound in env.

quote simply returns its argument. The argument is not evaluated and can be any R expression.

貌似看不懂,看几个例子来帮助理解。

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

这样看好像没什么区别。

f <- function(argX) {
   list(quote(argX), substitute(argX), argX)
}

suppliedArgX <- 100
f(argX = suppliedArgX)
# [[1]]
# argX
# 
# [[2]]
# suppliedArgX
# 
# [[3]]
# [1] 100

这时候可以看出两者处理函数的参数是不一样的,quote一直就是它括起的名称,而substitute如果参数名字有赋值,那就是赋值后的。更具体说是这样的:substitute解析每个元素进行替换,如果它不是env中的绑定符号,则保持不变。如果它是一个promise对象,即函数的形式参数或使用delayedAssign函数显式创建的,则promise的表达式替换成该符号。如果它是普通变量,则其值被替换,除非env是.GlobalEnv(全局环境),在这种情况下符号保持不变。
不好理解,再举个例子:

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

> quote(a)
[1] a

所以substitute有两种情况会发生名字的替换:一是在函数的参数中应用它时,二是当环境是非.GlobalEnv时。

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

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

说了半天,这和dplyr函数有什么关系呢?
因为R是惰性求值,对变量名的定义不像其他语言那么清晰。如
dplyr::summarise(mtcars, total_cyl = sum(cyl))中summarise和sum都是函数,mtcars是数据集,那么cyl是啥?

> cyl
Error: object 'cyl' not found

运行直接找不到。因为cyl没有被立刻评价,它像一个表达式对待随后被解析树解析,如果用substitue就可被解析出来。

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

根据quote和substitute我们可以以数据框列名为对象作为参数进行函数的编写,这种编写方式是非常符合人类正常思维的。我们下期再讲。

Ref: https://*.com/questions/46834655/whats-the-difference-between-substitute-and-quote-in-r

上一篇:Trim—Concatenate—Replace—Substitute


下一篇:Vim替换命令substitute小结-Vim入门教程(10)