2012-12-05 65 views
20

當我看到R的功能和我經常發現以下結構:的if/else構造內部和外部功能

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

這將運行沒有錯誤。但是執行內部函數代碼會拋出一個錯誤,因爲R可能假定語句在第一個賦值a <- 1之後完成,並且不能處理下面的其他語句。現在

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

,這對我來說很有意義,但我還是想明白爲什麼當內部或外部的功能執行的執行代碼的行爲不同。

回答

27

它使用一個交互式shell(REPL)運行腳本的結果:

第一支後殼已經看到了一個完整的語句,因此它假定你完成輸入。不幸的是,R使用相同的shell來解釋腳本,即使它們沒有以交互方式輸入 - 所以即使將if語句保存到一個文件並將其保存爲source(或將它管入R),您將在else分支上得到錯誤。

但下面的工作就好了:

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

這裏,解釋燕子行並執行它。

在你的功能中,人們會認爲同樣適用 - ,它的確如此!但是,功能本身在您的情況下以一個開放的大括號開頭,因此R必須閱讀,直到找到匹配的大括號。相比之下,利用這個函數聲明:

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

在R您可以定義功能,而機身四周括號。但是,上面的代碼將失敗,原因與沒有大括號的獨立if失敗相同。相比之下,如果我已將if寫入單行,則此代碼將再次運行。

順便說一下,你的函數使用一個賦值給一個未使用的變量。使用if殼內部時

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

...和相同的:你可以(應該)做以下代替

a <- if (exp) 1 else 2 

因爲R,if表達返回一個值。

+2

我不知道你解釋爲什麼多行'if ... else ...'在函數體內部被解釋爲單個語句。這是因爲當你開始鍵入'f < - function(exp = T){'時,R將繼續讀取,直到整個塊被匹配的'}'關閉。這將允許解釋者發現'else'是剛剛開始的'if'的延續。對? – flodel

+0

@ flodel啊,是的,我可能需要更清楚。但是你的猜想是真實的。並猜測當你移除函數體周圍的大括號時會發生什麼...... ;-) –

26

摘要:

只有兩種方式對R知道else子句屬於if語句上面:

  1. 整個if ... else語句(和也許還有其他一些陳述)用括號括起來;
  2. 其他詞與if子句的結尾出現在相同的行上。

證據:

上面的討論幫助我,但我希望我可以提供一個有用的狡辯。是的,這是正確的,

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

失敗的經典Error: unexpected 'else' in "else"消息,由於與R未能繼續讀過去1兩種方法已經被正確地主動提出[R繼續閱讀過去的1:

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

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

但有沒有提到第三條路---只要移動else了一條線。因此,下面的也適用,因爲[R知道要繼續讀過去的1:

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

我認爲最關鍵的一點是,要麼提振作用的整個身體,或者確保發生在同一行else if條款的結尾,以便R知道繼續閱讀。這就是單線解決方案的原因。這也是爲什麼這個工程:

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 
} 
+1

這是一個非常乾淨的解釋。謝謝。 –