R 中用于分解多行分配的 LHS 的语法

Syntax in R for breaking up LHS of assignment over multiple lines

R 中将赋值的 LHS 拆分为多行的语法是什么?在其他编程语言中你可以做到。

这个的一个用例(请不要让这个例子分散一般语法问题的注意力)是因为(我相信)R 不支持引用循环占位符变量,所以当使用非常for 循环中的深层嵌套数据结构(如列表数据帧的递归列表)有时您可能会有很长的赋值 LHS,例如

results$cases[[i]]$samples[[j]]$portions[[k]]$analytes[[l]]$column <- x

我知道,您可能会说为什么不使用嵌套 lapplys 或其他东西,但那是一个单独的讨论。

我尝试将 LHS 括在括号中,您得到了

Error: could not find function "(<-"

您可以在不属于名称的任意 2 个字符之间放置一个换行符,并且在换行符之前不会留下语法上完整的表达式(以便解析器知道要查找更多)。 None 看起来不错,但基本上在任何 [[$ 之后或 ]] 之前,您都可以换行。例如:

results$
  cases[[i]]$
    samples[[j]]$
      portions[[k]]$
        analytes[[l]]$
          column <- x

或者走极端,放入每个语法上有效的换行符(不引入括号,这会让你做更多):

results$
  cases[[
    i
  ]]$
    samples[[
      j
    ]]$
      portions[[
        k
      ]]$
        analytes[[
          l
        ]]$
          column <-
            x

有了圆括号,我们失去了 “不留下句法上完整的表达式” 规则,因为表达式在圆括号闭合之前不会完整。您可以在名称(对象或函数名称)中间以外的任何位置添加分隔符。对于这个例子,我不会为嵌套缩进烦恼。

(
  results
  $
  cases
  [[
    i
  ]]
  $
  samples
  [[
    j
  ]]
  $
  portions
  [[
    k
  ]]
  $
  analytes
  [[
    l
  ]]
  $
  column
  <-
  x
)

如果你想引起对正在分配的 x 的注意,你也可以使用正确的分配。

x -> results$cases[[i]]$samples[[j]]$
       portions[[k]]$analytes[[l]]$column

顺便提一下:元素运算符 [[ 支持列表的递归索引,如“递归 (list-like) 对象”下的 ?Extract 中所述。

需要注意的是,您必须为每个递归级别提供一个整数或字符索引。不支持混合,因此如果任何子列表没有 names 属性,您必须按整数索引。

x <- list(a = list(a1 = 1, a2 = 2), b = list(b1 = 3, b2 = 4))

x[[c(1L, 1L)]]
## [1] 1

x[[c("a", "a2")]]
## [1] 2

x[[c(2L, 1L)]] <- 30
x[[c(2L, 1L)]]
## [1] 30

x[[c("b", "b2")]] <- 40
x[[c("b", "b2")]]
## [1] 40

x[[list(1L, "a1")]]
## Error in x[[list(1L, "a1")]] : invalid subscript type 'list'

您始终可以实现支持混合类型索引的访问器:

rget <- function(x, i) {
    if (is.list(i)) {
        for (j in i) {
            x <- x[[j]]
        }
        x
    } else {
        x[[i]]
    }
}

`rset<-` <- function(x, i, value) {
    if (is.list(i)) {
        y <- x
        n <- length(i)
        ii <- integer(n)
        for (k in seq_len(n)) {
            j <- i[[k]]
            ii[k] <- if (is.character(j)) match(j, names(y)) else j
            y <- y[[j]]
        }
        x[[ii]] <- value
    } else {
        x[[i]] <- value
    }
    x
}

然后:

rget(x, list(1L, "a1"))
## [1] 1

rset(x, list(1L, "a1")) <- 10
rget(x, list(1L, "a1"))
## [1] 10

您只需要接受 for 循环的开销。