2010-01-24 101 views
28

爲什麼下面的代碼運行正常紅寶石打印進樣做語法

p (1..1000).inject(0) { |sum, i| 
    sum + i 
} 

但是,下面的代碼給出了一個錯誤

p (1..1000).inject(0) do |sum, i| 
    sum + i 
end 

warning: do not use Fixnums as Symbols 
in `inject': 0 is not a symbol (ArgumentError) 

他們不應等同?

回答

34

使用大括號書寫的塊綁定到注入方法,這是你的意圖,它會正常工作。

但是,封裝在do/end塊中的塊將綁定到p方法。正因爲如此,注入呼叫沒有關聯的塊。在這種情況下,inject會將參數(在本例中爲0)解釋爲要在每個對象上調用的方法名稱。 Bacuase 0不是可以轉換爲方法調用的符號,這會產生警告。

6

這看起來像中差DO /結束和支架之間的結合效果:

括號,你是上面使用,將結合到最後一個函數鏈而做/年底將結合第一。

我認爲這是一種奇怪的方式來說,但基本上第一個實例是將塊傳遞給函數'inject',而第二個實際上是試圖將塊傳遞給第一個方法'p'。

+1

「而第二個實際上是試圖將塊傳遞給第一種方法(1 ..1000)。」使「第一個方法」p「」,你是正確的。 – sepp2k 2010-01-24 16:50:32

+0

我改正了。乍一看忽略了上面的代碼! – Pete 2010-01-24 16:52:14

6

問題出在p開頭。如果忽略這些,你會看到,無論是做工精細:

# Works! 
[5, 6, 7].inject(0) do |sum, i| # Correctly binds to `inject`. 
    sum + i 
end 

# Works too! 
[5, 6, 7].inject(0) { |sum, i| # Correctly binds to `inject`. 
    sum + i 
} 

但是,這是行不通的:

# Kablammo! "p" came first, so it gets first dibs on your do..end block. 
# Now inject has no block to bind to! 
p [5, 6, 7].inject(0) do |sum, i| # Binds to `p` -- not what you wanted. 
    sum + i 
end