Knitr не находит функцию из предыдущего блока при использовании пользовательской функции knit и оценке функции в кавычках в списке - PullRequest
3 голосов
/ 23 апреля 2020

Я сталкивался со странными случаями, когда вязание документа с разметкой R не удается, когда чанк не может найти функцию, которая была определена в предыдущем чанке.

Я выделил одну из них ниже (наиболее Я мог бы), и вот как это терпит неудачу:

  • запускается без проблем при запуске каждого чанка вручную
  • вязание завершается неудачно, только если я использую пользовательскую функцию вязания в заголовке YAML
  • knitr не может найти функцию, только когда я eval цитируемое выражение И в функции списка / карты (lapply или purrr::)
    • т.е. нет проблем, если я сделаю eval(an_eval[[1]])

Воспроизводимое содержимое файла Rmd

---
output:
  html_document

knit: (function(input, encoding) {
    rmarkdown::render(
      input = input,
      encoding = encoding,
      output_file = 'a_file.html'
    )
  })
---

```{r}
library(knitr)
```

```{r define_function}
a_function <- function() return("a function")
```

```{r runs_fine}
a_function()
```

```{r this_fails}
an_exprs <- list(quote(a_function()))
lapply(an_exprs, eval)
```

Ошибка:

Quitting from lines 26-28 (Debug.Rmd) 
Error in a_function() : could not find function "a_function"
Calls: <Anonymous> ... withVisible -> eval -> eval -> lapply -> FUN -> FUN
Execution halted

Сессия:

> sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.4

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] knitr_1.28

1 Ответ

2 голосов
/ 23 апреля 2020

В этом случае необходимо указать аргумент envir для rmarkdown::render(), в противном случае по умолчанию используется среда parent.frame(), которая является внутренней средой (анонимной) функции, которую вы предоставили knit в YAML.

---
output:
  html_document

knit: (function(input, encoding) {
    rmarkdown::render(
      input = input,
      encoding = encoding,
      envir = globalenv()
    )
  })
---

```{r}
library(knitr)
```

```{r define_function}
a_function <- function() return("a function")
```

```{r runs_fine}
a_function()
```

```{r this_fails}
an_exprs <- list(quote(a_function()))
lapply(an_exprs, eval)
```
...