Каковы предостережения об использовании источника и parse & eval?
Краткая версия
Можно ли заменить
source(filename, local = TRUE, encoding = 'UTF-8')
с
eval(parse(filename, encoding = 'UTF-8'))
без риска поломки, чтобы исходные файлы UTF-8 работали в Windows?
Длинная версия
В настоящее время я загружаю определенные исходные файлы через
source(filename, local = TRUE, encoding = 'UTF-8')
Однако хорошо известно, что это не работает в Windows, полная остановка.
В качестве обходного пути предложил Джо Ченг, используя вместо этого
eval(parse(filename, encoding = 'UTF-8'))
Это работает довольно хорошо 1 но даже после ознакомления с исходным кодом source
я не понимаю, как они отличаются одной важной деталью:
Оба source
и sys.source
делают не просто parse
, а затем eval
содержимое файла. Вместо этого они анализируют содержимое файла, а затем перебирают вручную по разобранным выражениям и eval
их по одному. Я не понимаю, почему это было необходимо в sys.source
(source
по крайней мере использует его для отображения подробной диагностики, если это указано, но sys.source
делает ничего подобного):
for (i in seq_along(exprs)) eval(exprs[i], envir)
Какова цель выражения eval
ing отдельно? И почему он вместо итераций перебирает вместо индексов непосредственно? Какие еще оговорки существуют?
Чтобы уточнить: меня не интересуют дополнительные параметры source
и parse
, некоторые из которых могут быть установлены с помощью опций.
1 Причина, по которой source
отключена кодировкой, но parse
не сводится к тому, что source
пытается преобразовать входной текст. parse
не делает этого, он считывает содержимое байта содержимого как есть и просто отмечает его Encoding
как UTF-8
в памяти.
Ответы
Ответ 1
Это не полный ответ, поскольку он в первую очередь обращается к части вопроса seq_along
, но слишком длинный, чтобы включать в качестве комментариев.
Одно ключевое различие между seq_along
, за которым следует [
, а только с использованием подхода for i in x
(который, как я полагаю, схож с seq_along
, за которым следует [[
вместо [
), состоит в том, что первое сохраняет выражение. Вот пример, иллюстрирующий разницу:
> txt <- "x <- 1 + 1
+ # abnormal expression
+ 2 *
+ 3
+ "
> x <- parse(text=txt, keep.source=TRUE)
>
> for(i in x) print(i)
x <- 1 + 1
2 * 3
> for(i in seq_along(x)) print(x[i])
expression(x <- 1 + 1)
expression(2 *
3)
В качестве альтернативы:
> attributes(x[[2]])
NULL
> attributes(x[2])
$srcref
$srcref[[1]]
2 *
3
Имеет ли это какое-либо практическое влияние при сравнении с eval(parse(..., keep.source=T))
, я могу только сказать, что он может, но не может представить ситуацию, в которой он работает.
Обратите внимание, что выражение подмножества отдельно также приводит к подмножеству srcref
бизнес, который может быть полезен (возможно,?).