Какая разница между заместителем и цитатой в R
В официальных документах говорится:
substitute возвращает дерево разбора для (unevaluated) выражения expr, заменяя любые переменные, связанные в env.
quote просто возвращает свой аргумент. Аргумент не оценивается и может быть любым выражением R.
Но когда я пытаюсь:
> x <- 1
> substitute(x)
x
> quote(x)
x
Похоже, и quote
и substitute
возвращает выражение, переданное в качестве аргумента для них.
Итак, мой вопрос в том, какая разница между substitute
и quote
, и что это значит "заменять любые переменные, связанные в env"?
Ответы
Ответ 1
Вот пример, который может помочь вам легко увидеть разницу между quote()
и substitute()
в одном из параметров (аргументы функции обработки), где чаще всего используется substitute()
:
f <- function(argX) {
list(quote(argX), substitute(argX), argX)
}
suppliedArgX <- 100
f(argX = suppliedArgX)
# [[1]]
# argX
#
# [[2]]
# suppliedArgX
#
# [[3]]
# [1] 100
Ответ 2
Возможно, этот раздел документации поможет несколько:
Замена происходит путем изучения каждого компонента дерева разбора следующим образом: если он не является связанным символом в env, он не изменяется. Если это объект обещания, т.е. Формальный аргумент функции или явно созданный с использованием delayedAssign(), слот выражения обещания заменяет символ. Если это обычная переменная, ее значение заменяется, если только env не является.GlobalEnv, и в этом случае символ остается неизменным.
Обратите внимание на окончательный бит и рассмотрим этот пример:
e <- new.env()
assign(x = "a",value = 1,envir = e)
> substitute(a,env = e)
[1] 1
Сравните это с:
> quote(a)
a
Таким образом, есть две основные ситуации, когда подстановка будет происходить: когда мы используем ее для аргумента функции, а когда env
- это некоторая среда, .GlobalEnv
от .GlobalEnv
. Вот почему ваш конкретный пример сбивает с толку.
Для другого сравнения с quote
рассмотрим изменение функции myplot
в разделе примеров:
myplot <- function(x, y)
plot(x, y, xlab = deparse(quote(x)),
ylab = deparse(quote(y)))
и вы увидите, что quote
действительно не делает никакой замены.
Ответ 3
Что касается вашего вопроса, почему GlobalEnv рассматривается как исключение для замены, это всего лишь наследие определения языка S. From The R (https://cran.r-project.org/doc/manuals/r-release/R-lang.html # Замены):
Особое исключение для замены на верхнем уровне является, по общему признанию, своеобразным. Он был унаследован от S, и обоснование, скорее всего, не позволяет контролировать, какие переменные могут быть привязаны на этом уровне, так что было бы лучше просто сделать замену действием как цитатой.
Ответ 4
R имеет ленивую оценку, поэтому идентификация токена имени переменной немного менее понятна, чем на других языках. Это используется в таких библиотеках, как dplyr
где вы можете писать, например:
summarise(mtcars, total_cyl = sum(cyl))
Мы можем спросить, что означает каждый из этих токенов: summarise
и sum
определенные функции, mtcars
- это определенный кадр данных, total_cyl
- это аргумент ключевого слова для summarise
функции. Но что такое cyl
?
> cyl
Error: object 'cyl' not found
Это не что-то! Ну, еще нет. R не оценивает его сразу, но рассматривает его как выражение, которое будет разбираться позже с некоторым деревом разбора, которое отличается от глобальной среды, в которой работает ваша командная строка, в частности, где определены столбцы mtcars
. Где-то в кишках dplyr происходит нечто подобное:
> substitute(cyl, mtcars)
[1] 6 6 4 6 8 ...
Внезапно cyl
что-то значит. Для этой substitute
.
Итак, для чего quote
? Иногда вы хотите, чтобы ваше лениво оцениваемое выражение представлялось где-то еще до его оценки, т.е. Вы хотите отобразить фактический код, который вы пишете, без каких-либо (или только некоторых) значений, замененных. Документы, которые вы цитировали, объясняют это обычным для "информационных ярлыков для наборов данных и графиков".
Так, например, вы можете создать кавычное выражение, а затем оба напечатать неоценимое выражение в диаграмме, чтобы показать, как вы рассчитали и фактически вычислили с помощью выражения.
expr <- quote(x + y)
print(expr) # x + y
eval(expr, list(x = 1, y = 2)) # 3
Обратите внимание, что substitute
может также использовать этот трюк выражения, предоставляя вам возможность анализировать только его часть. Таким образом, его функции являются надмножеством quote
.
expr <- substitute(x + y, list(x = 1))
print(expr) # 1 + y
eval(expr, list(y = 2)) # 3