2010-01-24 12 views
28

Perché è che il seguente codice funziona benissimoRubino Stampa Inject Do Sintassi

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

Ma, il seguente codice dà un errore

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) 

Dovrebbero non essere equivalente?

risposta

34

Il blocco scritto utilizzando le parentesi graffe si lega al metodo di inserimento, che è l'intenzione dell'utente e funzionerà correttamente.

Tuttavia, il blocco incapsulato nel blocco do/end si associa al metodo p. Per questo motivo, la chiamata inject non ha un blocco associato. In questo caso, inject interpreterà l'argomento, in questo caso 0, come un nome di metodo da chiamare su ogni oggetto. Bacuase 0 non è un simbolo che può essere convertito in una chiamata al metodo, questo produrrà un avvertimento.

6

Questo appare come un effetto della differenza di associazione tra do/fine e staffe:

parentesi, utilizzato come si è sopra, si legheranno l'ultima funzione, mentre incatenato fare/fine lo legherà alla prima.

Penso che sia un modo strano per dirlo, ma fondamentalmente la prima istanza passa il blocco alla funzione 'inietti', mentre il secondo sta effettivamente cercando di passare il blocco al primo metodo 'p'.

+1

", mentre il secondo è in realtà cercando di passare il blocco al primo metodo (1 ..1000)." Fallo "al primo metodo' p' "e sei corretto. – sepp2k

+0

L'ho corretto. trascurato che nel codice sopra a prima vista! – Pete

6

Il problema è con lo p all'inizio. Se si omette questi vedrai che entrambi funzionano bene:

# 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 
} 

Ma questo non funzionerà:

# 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