【问题标题】:What are the caveats of using source versus parse & eval?使用 source 与 parse & eval 的注意事项是什么?
【发布时间】:2014-08-18 17:24:19
【问题描述】:

短版

我可以换吗

source(filename, local = TRUE, encoding = 'UTF-8')

eval(parse(filename, encoding = 'UTF-8'))

在没有任何损坏风险的情况下,让 UTF-8 源文件在 Windows 上工作?

加长版

我目前正在通过

加载特定的源文件
source(filename, local = TRUE, encoding = 'UTF-8')

但是,众所周知,this does not work on Windows,句号。

作为一种解决方法,Joe Cheng suggested 改为使用

eval(parse(filename, encoding = 'UTF-8'))

这似乎工作得很好1 但是即使在查阅了source 的源代码之后,我还是不明白它们在一个关键细节上有什么不同:

sourcesys.source只是简单地parse 然后eval 文件内容。相反,它们解析文件内容,然后手动迭代解析的表达式,然后eval 将它们一一进行。我不明白为什么在sys.source 中需要这样做(source 至少使用它来显示详细诊断,如果有指示的话;但sys.source 确实nothing of the kind):

for (i in seq_along(exprs)) eval(exprs[i], envir)

分别evaling 语句的目的是什么? 为什么它要遍历索引而不是直接遍历子表达式?还有什么其他注意事项?

澄清一下:我关心sourceparse的附加参数,其中一些可以通过选项设置。


1source 被编码绊倒,而parse 不是因为source 试图转换输入文本。 parse 不做这样的事情,它按原样读取文件的字节内容,并在内存中简单地将其Encoding 标记为UTF-8

【问题讨论】:

  • @Spacedman 为什么这些命令还存在呢? (出于更具体的原因:因为我正在处理 alternative package system。)
  • 啊。仍在研究该模块系统。仙女纳芙。
  • 所以这个问题纯粹是“eval(exprs)for(ex in exprs)eval(ex)for(i in seq_along(exprs))eval(exprs[i])之间有什么区别?”? (在这里和那里给或接受envir)它有点乱。我的意思是,所有 UTF 的东西都是无关紧要的,你真正的问题出现在一半。
  • 所以只是为了澄清一点:Joe Cheng 的eval(parse(...)) 解决方法到目前为止工作得很好,但您想知道是否存在任何可能在某些时候咬人的后果差异, 正确的?而且你自然有点不安,因为你没有完全遵循源代码的作用(以及你在哪里遵循它,你并不总是理解它的基本原理)......你的终极(但可能太模糊-for-SO) 问题,“有人可以确认eval(parse(...))source(...) 的可靠替代品吗?
  • evaluate 包作者(Yihui、Hadley 和 Barret Schloerke)可能对您的问题有一些有趣的见解。 evaluateknitr 对 R 代码的逐语句评估的基础,它通过解析然后“手动”迭代解析的表达式来工作,依次评估每个表达式。如果有人知道这样做或不这样做的潜在“陷阱”,我想他们可能就是那些。

标签: r eval


【解决方案1】:

这不是一个完整的答案,因为它主要解决问题的seq_along 部分,但太长而无法包含在 cmets 中。

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 业务获取子集,这可能很有用(...也许?)。

【讨论】:

    猜你喜欢
    • 2018-12-15
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 2014-03-08
    • 2010-11-24
    相关资源
    最近更新 更多