14

我是一个顽固的用户,=而不是一直使用<-,显然许多 R 程序员对此会皱眉头。我根据包编写了formatR可以替换=<-parser。你们有些人可能知道,parser几天前在 CRAN 上成为孤儿。虽然它现在又回来了,但这让我对依赖它犹豫不决。我想知道是否有另一种方法可以安全地替换=<-,因为不是所有=的平均分配,例如fun(a = 1). 正则表达式不太可能是可靠的(参见函数的第18 行),但如果您能改进我的,我将不胜感激。也许包裹可以提供帮助?mask.inline()formatRcodetools

几个测试用例:

# should replace
a = matrix(1, 1)
a = matrix(
  1, 1)

(a = 1)
a =
  1

function() {
  a = 1
}

# should not replace
c(
  a = 1
  )

c(
  a = c(
  1, 2))
4

3 回答 3

4

这个答案使用正则表达式。有一些边缘情况会失败,但对于大多数代码来说应该没问题。如果您需要完美匹配,则需要使用解析器,但如果遇到问题,可以随时调整正则表达式。

当心

#quoted function names
`my cr*azily*named^function!`(x = 1:10)
#Nested brackets inside functions
mean(x = (3 + 1:10))
#assignments inside if or for blocks
if((x = 10) > 3) cat("foo")
#functions running over multiple lines will currently fail
#maybe fixable with paste(original_code, collapse = "\n")
mean(
  x = 1:10
)

该代码基于?regmatches页面上的示例。基本思想是:将函数内容交换为占位符,进行替换,然后将函数内容放回原处。

#Sample code.  For real case, use 
#readLines("source_file.R")
original_code <- c("a = 1", "b = mean(x = 1)")

#Function contents are considered to be a function name, 
#an open bracket, some stuff, then a close bracket.
#Here function names are considered to be a letter or
#dot or underscore followed by optional letters, numbers, dots or 
#underscores.  This matches a few non-valid names (see ?match.names
#and warning above).
function_content <- gregexpr(
  "[[:alpha:]._][[:alnum:._]*\\([^)]*\\)", 
  original_code
)

#Take a copy of the code to modify
copy <- original_code

#Replace all instances of function contents with the word PLACEHOLDER.
#If you have that word inside your code already, things will break.
copy <- mapply(
  function(pattern, replacement, x) 
  {
    if(length(pattern) > 0) 
    {
      gsub(pattern, replacement, x, fixed = TRUE) 
    } else x
  }, 
  pattern = regmatches(copy, function_content), 
  replacement = "PLACEHOLDER", 
  x = copy,
  USE.NAMES = FALSE
)

#Replace = with <-
copy <- gsub("=", "<-", copy)

#Now substitute back your function contents
(fixed_code <- mapply(
  function(pattern, replacement, x) 
  {
      if(length(replacement) > 0) 
      {
          gsub(pattern, replacement, x, fixed = TRUE) 
      } else x
  }, 
  pattern = "PLACEHOLDER", 
  replacement = regmatches(original_code, function_content), 
  x = copy,
  USE.NAMES = FALSE
))

#Write back to your source file
#writeLines(fixed_code, "source_file_fixed.R")
于 2012-07-02T10:58:39.757 回答
4

Kohske 向该软件包发送了一个拉取请求,该formatR软件包使用该软件包解决了问题codetools。基本思路是设置一个code walker来遍历代码;当它检测到=作为函数调用的符号时,将其替换为<-. 这是由于 R: 的“Lisp 本质”x = 1实际上是`=`(x, 1)(我们将其替换为`<-`(x, 1));当然,=fun(x = 1).

formatR(>= 0.5.2) 已经摆脱了对parser包的依赖,replace.assign现在应该是健壮的。

于 2012-07-04T02:04:35.357 回答
-3

最安全(可能也是最快)的替换=方式<-是直接键入<-而不是尝试替换它。

于 2012-07-01T08:20:30.353 回答