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

时间:2022-08-21 22:53:06

When I look at R functions I often find the following structure:

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

f <- function(exp=T) {
  if (exp)
    a <- 1
  else
    a <- 2
}
f()
f(F)

This will run without error. But executing the inner function code throws an error as R probably assumes that the statement is finished after the first assignment a <- 1 and cannot handle the following else.

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

exp=T
if (exp)
  a <- 1
else
  a <- 2

Now, this makes sense to me, but I still would like to understand why the behaviour of the executed code differs when executed inside or outside a function.

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

2 个解决方案

#1


27  

It’s a consequence of using an interactive shell (REPL) to run scripts:

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

After the first branch the shell has seen a complete statement so it assumes that you’re done typing. Unfortunately, R uses the same shell for interpreting scripts even if they are not typed in interactively – so even when you save the if statement to a file and source it (or pipe it into R) you will get the error on the else branch.

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

But the following will work just fine:

但以下工作会很好:

if (exp) a <- 1 else a <- 2

Here, the interpreter swallows the line and executes it.

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

In your function one would assume that the same applies – and it does! However, the function itself starts with an open brace in your case, so R has to read until it finds the matching closing brace. By contrast, take this function declaration:

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

f <- function (exp)
    if (exp)
        a <- 1
    else
        a <- 2

In R you can define functions without braces around the body. But the above code will fail for the same reason that the standalone if without braces fails. By contrast, if I had written the if on a single line this code would once again work.

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

Incidentally, your function uses an assignment to a variable that isn’t used. You can (should) do the following instead:

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

f <- function (exp) {
    if (exp)
        1
    else
        2
}

… and the same when using if inside the shell:

...和在shell中使用if时相同:

a <- if (exp) 1 else 2

because in R, if is an expression which returns a value.

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

#2


26  

Executive Summary:

执行摘要:

There are only two ways for R to know that an else clause belongs to the if clause above it:

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

  1. The entire if...else statement (and perhaps other statements as well) is enclosed in braces;
  2. 整个if ... else语句(也许还有其他语句)用大括号括起来;
  3. The word else appears on the same line as the end of the if clause.
  4. 单词else出现在与if子句结尾相同的行上。

Evidence:

证据:

The above discussion helped me, but I hope I can offer a useful quibble. Yes, it is correct that

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

f <- function (exp)
    if (exp)
        1  
    else
        2

fails with the classic Error: unexpected 'else' in "else" message due to R's failure to keep reading past the 1. Two ways have been correctly offered to make R keep reading past the 1:

由于R未能继续读取而导致经典错误:“else”消息中出现意外的“其他”意外1.已正确提供两种方式使R继续读取1:

f <- function (exp) {
    if (exp)
        1  
    else
        2
}

and

f <- function (exp) if (exp) 1 else 2

But there is a third way not yet mentioned---just move else up a line. Thus, the following also works because R knows to keep reading past the 1:

但还有第三种方法尚未提及 - 只需将其他方向移动一线即可。因此,以下也有效,因为R知道继续阅读1:

f <- function (exp)
    if (exp)
        1  else
        2

I think the key point is to either brace the entire body of the function, or make sure the else occurs on the same line as the end of the if clause so that R knows to keep reading. That's why the one-line solution works. It is also why this works:

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

f <- function (exp)
    if (exp) {
        1
    } else
        2

But this fails:

但这失败了:

f <- function (exp)
    if (exp) {
        1
    }  
    else
        2

And using the more standard bracing of the function body, this works too:

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

f <- function (exp) {
    if (exp) {
        1
    }  
    else
        2
}

But whether or not we are building a function is a red herring. What matters is only braces and location of else. Thus, these work:

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

{
    if (exp) {
        1
    }  
    else
        2
}


if (exp) {
    1
} else
    2

but this fails:

但这失败了:

if (exp) {
    1
} 
else
    2

and to demonstrate my assertion 1 at the top, this works:

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

{
x <- 4
if (exp) 
    1
else
    2
}

#1


27  

It’s a consequence of using an interactive shell (REPL) to run scripts:

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

After the first branch the shell has seen a complete statement so it assumes that you’re done typing. Unfortunately, R uses the same shell for interpreting scripts even if they are not typed in interactively – so even when you save the if statement to a file and source it (or pipe it into R) you will get the error on the else branch.

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

But the following will work just fine:

但以下工作会很好:

if (exp) a <- 1 else a <- 2

Here, the interpreter swallows the line and executes it.

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

In your function one would assume that the same applies – and it does! However, the function itself starts with an open brace in your case, so R has to read until it finds the matching closing brace. By contrast, take this function declaration:

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

f <- function (exp)
    if (exp)
        a <- 1
    else
        a <- 2

In R you can define functions without braces around the body. But the above code will fail for the same reason that the standalone if without braces fails. By contrast, if I had written the if on a single line this code would once again work.

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

Incidentally, your function uses an assignment to a variable that isn’t used. You can (should) do the following instead:

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

f <- function (exp) {
    if (exp)
        1
    else
        2
}

… and the same when using if inside the shell:

...和在shell中使用if时相同:

a <- if (exp) 1 else 2

because in R, if is an expression which returns a value.

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

#2


26  

Executive Summary:

执行摘要:

There are only two ways for R to know that an else clause belongs to the if clause above it:

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

  1. The entire if...else statement (and perhaps other statements as well) is enclosed in braces;
  2. 整个if ... else语句(也许还有其他语句)用大括号括起来;
  3. The word else appears on the same line as the end of the if clause.
  4. 单词else出现在与if子句结尾相同的行上。

Evidence:

证据:

The above discussion helped me, but I hope I can offer a useful quibble. Yes, it is correct that

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

f <- function (exp)
    if (exp)
        1  
    else
        2

fails with the classic Error: unexpected 'else' in "else" message due to R's failure to keep reading past the 1. Two ways have been correctly offered to make R keep reading past the 1:

由于R未能继续读取而导致经典错误:“else”消息中出现意外的“其他”意外1.已正确提供两种方式使R继续读取1:

f <- function (exp) {
    if (exp)
        1  
    else
        2
}

and

f <- function (exp) if (exp) 1 else 2

But there is a third way not yet mentioned---just move else up a line. Thus, the following also works because R knows to keep reading past the 1:

但还有第三种方法尚未提及 - 只需将其他方向移动一线即可。因此,以下也有效,因为R知道继续阅读1:

f <- function (exp)
    if (exp)
        1  else
        2

I think the key point is to either brace the entire body of the function, or make sure the else occurs on the same line as the end of the if clause so that R knows to keep reading. That's why the one-line solution works. It is also why this works:

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

f <- function (exp)
    if (exp) {
        1
    } else
        2

But this fails:

但这失败了:

f <- function (exp)
    if (exp) {
        1
    }  
    else
        2

And using the more standard bracing of the function body, this works too:

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

f <- function (exp) {
    if (exp) {
        1
    }  
    else
        2
}

But whether or not we are building a function is a red herring. What matters is only braces and location of else. Thus, these work:

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

{
    if (exp) {
        1
    }  
    else
        2
}


if (exp) {
    1
} else
    2

but this fails:

但这失败了:

if (exp) {
    1
} 
else
    2

and to demonstrate my assertion 1 at the top, this works:

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

{
x <- 4
if (exp) 
    1
else
    2
}