if/else构造内部和外部函数

Mar*_*ann 22 if-statement r

当我查看R函数时,我经常会发现以下结构:

f <- function(exp=T) {
  if (exp)
    a <- 1
  else
    a <- 2
}
f()
f(F)
Run Code Online (Sandbox Code Playgroud)

这将运行没有错误.但是执行内部函数代码会引发错误,因为R可能假定语句在第一次赋值后完成,a <- 1并且无法处理以下其他内容.

exp=T
if (exp)
  a <- 1
else
  a <- 2
Run Code Online (Sandbox Code Playgroud)

现在,这对我来说很有意义,但我仍然想了解为什么执行代码的行为在函数内部或外部执行时会有所不同.

Jer*_*tah 30

执行摘要:

R只有两种方法可以知道else子句属于它上面的if子句:

  1. 整个if ... else语句(也许还有其他语句)用大括号括起来;
  2. 单词else出现在与if子句结尾相同的行上.

证据:

上面的讨论帮助了我,但我希望我能提供一个有用的狡辩.是的,这是正确的

f <- function (exp)
    if (exp)
        1  
    else
        2
Run Code Online (Sandbox Code Playgroud)

Error: unexpected 'else' in "else"由于R未能继续阅读,因此失败了经典信息1.正确提供了两种方法让R继续读取1:

f <- function (exp) {
    if (exp)
        1  
    else
        2
}
Run Code Online (Sandbox Code Playgroud)

f <- function (exp) if (exp) 1 else 2
Run Code Online (Sandbox Code Playgroud)

但还有第三种方式尚未提及 - 只需向上移动else一条线.因此,以下也有效,因为R知道继续阅读1:

f <- function (exp)
    if (exp)
        1  else
        2
Run Code Online (Sandbox Code Playgroud)

我认为关键是要么支撑函数的整个主体,要么确保它else与if子句的结尾在同一行上,以便R知道继续读取.这就是单线解决方案有效的原因.这也是为什么这样做的原因:

f <- function (exp)
    if (exp) {
        1
    } else
        2
Run Code Online (Sandbox Code Playgroud)

但这失败了:

f <- function (exp)
    if (exp) {
        1
    }  
    else
        2
Run Code Online (Sandbox Code Playgroud)

使用功能体的更标准支撑,这也适用:

f <- function (exp) {
    if (exp) {
        1
    }  
    else
        2
}
Run Code Online (Sandbox Code Playgroud)

但是,我们是否正在建立一个功能是一个红色的鲱鱼.重要的只是括号和位置else.因此,这些工作:

{
    if (exp) {
        1
    }  
    else
        2
}


if (exp) {
    1
} else
    2
Run Code Online (Sandbox Code Playgroud)

但这失败了:

if (exp) {
    1
} 
else
    2
Run Code Online (Sandbox Code Playgroud)

并且为了在顶部演示我的断言1,这有效:

{
x <- 4
if (exp) 
    1
else
    2
}
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 28

这是使用交互式shell(REPL)运行脚本的结果:

在第一个分支之后,shell看到了一个完整的语句,因此它假设你已经完成了输入.不幸的是,R使用相同的shell来解释脚本,即使它们没有以交互方式输入 - 所以即使将if语句保存到文件中source(或将其管道输入R),您也会在else分支上得到错误.

但以下工作会很好:

if (exp) a <- 1 else a <- 2
Run Code Online (Sandbox Code Playgroud)

这里,解释器吞下该行并执行它.

在你的函数中,人们会认为同样适用 -  它确实如此!但是,函数本身在您的情况下以开括号开始,因此R必须读取,直到找到匹配的右括号.相比之下,采取此函数声明:

f <- function (exp)
    if (exp)
        a <- 1
    else
        a <- 2
Run Code Online (Sandbox Code Playgroud)

在R中,您可以定义身体周围没有括号的功能.但是上面的代码将失败的原因与if没有大括号的独立版本失败的原因相同.相比之下,如果我在if一行上编写了这段代码,那么这段代码将再次起作用.

顺便提一下,您的函数使用对未使用的变量的赋值.您可以(应该)执行以下操作:

f <- function (exp) {
    if (exp)
        1
    else
        2
}
Run Code Online (Sandbox Code Playgroud)

... if在shell中使用时也一样:

a <- if (exp) 1 else 2
Run Code Online (Sandbox Code Playgroud)

因为在R中,if是一个返回值的表达式.

  • 我不确定你解释了为什么多行`if ... else ...`在函数体内被解释为单个语句.这是因为当你开始输入`f < - function(exp = T){`时,R将继续读取,直到用匹配的`}`关闭整个块.这将允许解释器发现`else`是上面启动的`if`的延续.对? (2认同)