2009-12-02 42 views
0

I recently discovered您可以用if-else塊有條件地賦值。從if-else塊分配值(它是如何工作的?)

y <- if(condition) 1 else 2 

我意識到,使用情況,這是有限的:如果你已經矢量化的代碼,你可以使用ifelse函數。有一個性能優勢:if-else比我的機器上的標量案例中的ifelse運行速度快35倍(儘管您需要調用它幾百萬次才能注意到其中的很大不同)。

什麼是我的問題是,我不知道爲什麼這段代碼工作—我很驚訝,它不只是拋出一個錯誤。

另一個例子表明,如果塊的功能類似於函數—,它們會自動返回塊中的最後一個值(儘管在它們中不能使用return語句)。

y <- if(TRUE) 
{ 
    y <- 3 
    4 
} # y is 4 

在此基礎上,我猜,也許當你如果塊輸入了另一個環境中創建的,但是這似乎並不如此。

if(TRUE) sys.frames() # NULL 

有誰能告訴我發生了什麼問題嗎?

回答

8

讓我專注於

What is bugging me is that I can't work out why this code works—I was amazed that it doesn't just throw an error.

你爲什麼這麼認爲?什麼情況是,我們有

  1. y被分配一個表達式
  2. 是表達作爲一個如果if() ...
  3. 導致無論是TRUEFALSE測試
  4. 領導到兩個分支之一被輸入
  5. 導致正在評估的相應代碼
  6. 導致其最終值爲右手邊
  7. 導致該值被分配到y

似乎是合乎邏輯我。

+0

也許我過(或下)認爲這,我們可以把它歸結爲非常聰明的解析。爲了記錄,當你在MATLAB中嘗試這樣的事情時,你會得到一個錯誤:'如果'非法使用保留關鍵字'。' – 2009-12-02 17:10:10

+1

雖然R不是MATLAB,但沒有理由要遵循MATLAB的規則。這裏,if塊中最後一條語句的值被賦值給y。這個聲明是標量4. – Sharpie 2009-12-02 17:25:03

+0

Python也會中斷,就像C#一樣(儘管您可以使用'?'運算符,正如Ken指出的那樣)。我認爲關鍵的一點是,在作出分配之前,聲明的右側被視爲表達式並評估**。 – 2009-12-02 18:34:16

2

這不是很深 - 很多語言都使用「val = x?y:z」構造。在R中,這只是摺疊成一個if/else結構,所以你寫「val = if(x)y else z」。調用與相關(懶惰評估)子表達式作爲參數

+0

好點–我想它的解析方式或多或少與三元運算符相同。 – 2009-12-02 18:30:30

4

控制結構如if(....) ... else ...相當於功能:

`if`(TRUE, "yes", "no") 

基本上,if特殊原語功能:

R> sapply(ls("package:base", all=TRUE), function(x) is.primitive(get(x)))["if"] 
    if 
TRUE 
R> sapply(ls("package:base", all=TRUE), function(x) typeof(get(x)))["if"] 
     if 
"special" 

相關章節(3.2節)1)R Language Definition manual說:

因爲如果/ else語句與其他語句相同,您可以指定它們的值。下面的兩個例子是等價的。

R> if(any(x <= 0)) y <- log(1+x) else y <- log(x) 
R> y <- if(any(x <= 0)) log(1+x) else log(x) 
+0

@ rcs:感謝您的參考。我應該按照手冊中的方式來更清楚地瞭解R在做什麼。 – 2009-12-03 13:20:55

+0

我也可以推薦數據分析軟件中的第13章(如何工作) - 編程與R(約翰錢伯斯) – rcs 2009-12-03 14:00:58

3

關於你問題的第二部分 - {}用於組表達式,它比在函數定義不同勢。正如你在讀help("Paren")

For ‘{’ , the result of the last expression evaluated.

但所有表達式在當前的環境進行評估:

y <- if (TRUE) { 
    print(paste("Current frame:",sys.nframe())) 
    y <- 3 
    z <- 5 
    4 
} 
# [1] "Current frame: 0" 
# result: 
y # [1] 4 
z # [1] 5 

# compare to use function: 
v <- if(TRUE) (function(){  
    print(paste("Current frame:",sys.nframe())) 
    v <- 3 
    w <- 5 
    4 
})() 
# [1] "Current frame: 1" 
v # [1] 4 
w # Error: object 'w' not found 

結論是塊不表現得像功能

編輯: 如果你想使用塊作爲功能你可以使用local

a <- if (TRUE) local({ 
    print(paste("Current frame:",sys.nframe())) 
    a <- 3 
    b <- 5 
    4 
}) 
# [1] "Current frame: 6" 
a # [1] 4 
b # Error: object 'b' not found 

那麼你可以使用return太:

a <- if (TRUE) local({ 
    print(paste("Current frame:",sys.nframe())) 
    a <- 3 
    b <- 5 
    return(7) 
    4 
}) 
# [1] "Current frame: 6" 
a # [1] 7 
b # Error: object 'b' not found 
+0

@Marek:一個有趣的分析。我沒有考慮過(而且會是功能。 – 2009-12-03 13:05:21

相關問題