2009-08-26 11 views
11

Ho riscontrato un problema interessante mentre utilizzavo il metodo "tocca" sugli oggetti di tipo "String".Il metodo "tocca" sull'oggetto String non restituisce il risultato previsto

"abc".tap { |o| o = "xyz" } # this line returns "abc" instead of "xyz" 

Il metodo "tocca" funziona su oggetti di altri tipi.

[].tap { |o| o << "xyz" } # this line returns ["xyz"] as expected 

Sto usando Rails 2.3.2 e Ruby 1.8.6 su Windows XP.

Cosa mi manca qui?

Aggiornamento 1: ho risolto questo problema. È stato un errore di utilizzo da parte mia. Nel primo scenario stavo riassegnando il valore al parametro block invece di modificarlo. Sono stato in grado di riscrivere il codice e ottenere il risultato previsto.

"abc".tap { |o| o.replace "xyz" } 

Aggiornamento 2: il codice utilizzato qui è solo per dimostrare il problema. Il mio codice attuale non assomiglia a questo.

+0

Potremmo avere un esempio reale di ciò che stai cercando di fare? –

+1

Ho risolto questo problema. È stato un errore di utilizzo da parte mia. Nel primo scenario stavo riassegnando il valore al parametro di blocco invece di modificarlo. Sono stato in grado di riscrivere il codice e ottenere il risultato previsto. "abc" .tap {| o | o.replace "xyz"} –

risposta

8

Il rubinetto dell'oggetto # restituisce sempre l'oggetto originale passato dopo l'esecuzione del blocco, anche se il blocco restituisce qualcosa di diverso.

Il vantaggio qui è che è possibile mettere il rubinetto nel mezzo di una catena e verificare il valore di un oggetto senza modificare il valore originale.

Ciò significa che se si passa "abc" a toccare, eseguirà il blocco e restituirà "abc". Il tuo compito a o non significa nulla a causa dell'ambito. Allo stesso modo, se si passa a un array vuoto in tocco, restituirebbe un array vuoto. Tuttavia, nel tuo secondo esempio, hai modificato il valore originale. Operazioni che modificano l'originale come < < o gsub! o allo stesso modo modificherà l'oggetto prima che sia restituito, quindi si ottiene un valore diverso.

Scopri http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions per alcuni esempi più interessanti su come utilizzare il tocco. Non usarlo per assegnazione o modifica o otterrai risultati impeccabili.

Aggiornamento: Per la modifica, perché questo risolve il problema? Non capisco perché chiamerai tap per fare una sostituzione quando puoi semplicemente chiamare replace sull'oggetto stesso. Quale vantaggio ti offre?

+2

Sì, non ha senso usare 'tap' per fare una semplice sostituzione. Il mio codice attuale non assomiglia a questo. Invece di postare una grossa porzione di codice, ho trovato questo esempio per riprodurre il problema. Tendo ad usare "tap" per il debug. Recentemente ho iniziato a usare 'tap' al posto di 'return'. Una volta riletto il codice sorgente di Rails per il metodo tap, il mio errore è diventato evidente. –

Problemi correlati