24

R 関数を見ると、次のような構造がよく見られます。

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

これはエラーなしで実行されます。しかし、内部関数コードを実行するとエラーがスローされます。これは、R がおそらく最初の代入後にステートメントが終了したと想定しa <- 1、次の else を処理できないためです。

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

さて、これは私には理にかなっていますが、実行されたコードの動作が関数内または関数外で実行されると異なる理由を理解したいと思います。

4

2 に答える 2

35

エグゼクティブサマリー:

R が else 節がその上の if 節に属していることを知る方法は 2 つしかありません。

  1. if...else ステートメント全体 (およびおそらく他のステートメントも) は中括弧で囲まれています。
  2. else という単語は、if 句の末尾と同じ行に表示されます。

証拠:

上記の議論は私を助けてくれましたが、役に立つ質問を提供できることを願っています. はい、それは正しいです

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

R が 1 を超えて読み続けることができないため、従来Error: unexpected 'else' in "else"のメッセージで失敗します。R が 1 を超えて読み続けるようにするための 2 つの方法が正しく提供されています。

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

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

しかし、まだ言及されていない 3 番目の方法がありelseます。したがって、R は 1 を超えて読み続けることを知っているため、以下も機能します。

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

重要なポイントは、関数の本体全体を中括弧にするかelse、if 句の最後と同じ行に発生するようにして、R が読み続けることを認識できるようにすることだと思います。そのため、1 行のソリューションが機能します。これが機能する理由でもあります。

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

しかし、これは失敗します:

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

関数本体のより標準的なブレースを使用すると、これも機能します。

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

しかし、関数を構築しているかどうかは、重要な問題です。重要なのは、ブレースと の場所だけですelse。したがって、これらは次のように機能します。

{
    if (exp) {
        1
    }  
    else
        2
}


if (exp) {
    1
} else
    2

しかし、これは失敗します:

if (exp) {
    1
} 
else
    2

上の私のアサーション 1 を示すために、これは機能します。

{
x <- 4
if (exp) 
    1
else
    2
}
于 2012-12-14T20:40:30.137 に答える
30

これは、インタラクティブ シェル ( REPL ) を使用してスクリプトを実行した結果です。

最初の分岐の後、シェルは完全なステートメントを認識したため、入力が完了したと想定します。残念ながら、R はスクリプトを対話的に入力しなくても、同じシェルを使用してスクリプトを解釈します。そのため、ifステートメントをファイルに保存しsourceて (または R にパイプして) も、elseブランチでエラーが発生します。

ただし、次の場合は問題なく動作します。

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

ここで、インタプリタはその行を飲み込んで実行します。

あなたの関数では、同じことが当てはまると仮定するでしょう - <em>そしてそうです! ただし、この場合、関数自体は左中かっこで始まるため、R は一致する右中かっこが見つかるまで読み取る必要があります。対照的に、次の関数宣言を見てください。

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

R では、本体を中かっこなしで関数を定義できます。ifしかし、中括弧なしのスタンドアロンが失敗するのと同じ理由で、上記のコードは失敗します。対照的にif、1 行で記述した場合、このコードは再び機能します。

ちなみに、あなたの関数は、使用されていない変数への代入を使用しています。代わりに次のことを行うことができます(すべきです):

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

...そして、ifシェル内で使用する場合も同じです:

a <- if (exp) 1 else 2

Rでは、値を返すifであるためです。

于 2012-12-05T13:16:52.003 に答える