Поведение привязки меняется в зависимости от вызова (блестящий или не блестящий) - PullRequest
1 голос
/ 17 февраля 2020

Вызов следующего кода имеет различное поведение привязки, в зависимости от того, работает он под блеском или нет. Я никак не могу это оправдать.

# app.R
source("b.R")
print("foo after source")
print(foo)
x()
print("setting foo in app.R")
foo <- c(1,2)
x()
# b.R
foo <- c("XXX")

x <- function() {
  print("inside function")
  print(foo)
}

Результат, если я вызову его с помощью Rscript:

whatever$ Rscript app.R 
[1] "foo after source"
[1] "XXX"
[1] "inside function"
[1] "XXX"
[1] "setting foo in app.R"
[1] "inside function"
[1] 1 2

Результат, если я вызову его под блестящим

> shiny::runApp('whatever')
Loading required package: shiny
[1] "foo after source"
[1] "XXX"
[1] "inside function"
[1] "XXX"
[1] "setting foo in app.R"
[1] "inside function"
[1] "XXX"

Это похоже на раннее связывание с закрытием функции только при работе под сиянием.

1 Ответ

2 голосов
/ 17 февраля 2020

То, что здесь происходит, заключается в том, что когда вы запускаете shiny::runApp(), spark создает собственную среду для запуска всего кода блестящего кода (я думаю, что это связано с this ). Но когда вы вызываете source() напрямую, отдельная среда не создается, и все идет прямо в глобальную среду. Это можно увидеть, добавив print(environment()) в файл app.R. Вы увидите, когда вы source("app.R") вернете <environment: R_GlobalEnv>, но когда вы позвоните shiny::runApp(), вы увидите другое имя среды.

Так что, когда вы наберете source() в app.R, снова это загрузка всего контента в локальную среду по умолчанию. Это создает foo<-"XXX" в глобальной среде, и среда для x() устанавливается в глобальную среду. Это верно для обоих вызовов. Но когда вы запускаете его с помощью shiny::runApp, это не работает в глобальной среде, поэтому, когда вы делаете foo <- c(1,2), вы обновляете не глобальную среду, а только локальную блестящую среду. Глобальный foo все еще существует, и благодаря лексической области видимости, глобальное значение - это то, что x найдет.

Быстрое решение проблемы - использовать

source("b.R", local=TRUE)

в app.R. Это загрузит значения из b.R в локальную среду, а не в глобальную среду. Это будет работать в обоих случаях, поскольку вызов source() непосредственно в "app.R" уже будет выполняться в глобальной среде, поэтому он не будет работать по-другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...