Domanda

Sono stato morso un paio di volte dimenticando che x = y in Ruby fa riferimento lo stesso oggetto come y;Sono troppo abituato a lingue dove significa, in termini di rubino, x = y.dup.Dimenticando questo, cambia inavvertitamente y quando penso che sia sicuro sul lato destro del compito.

Posso vedere che avrebbe senso evitare semplici incarichi x = y senza una ragione speciale, ma la stessa cosa può essere in agguato in altri luoghi come

name = (person.last_name.blank? ? 'unknown' : person.last_name)
.

Dove un successivo name << title sarebbe in realtà cambiare persona .last_name e non solo il nome.

Se questo è successo anche a te, come hai imparato a evitarlo?Ci sono certe bandiere o modelli rossi da cercare?Guardi con sospetto ad ogni incarico che fai?Usi molto .dup?Non so se l'utilizzo di Ruby diventerà mai la seconda natura per me, quindi qualsiasi consiglio utile sarebbe il benvenuto.

È stato utile?

Soluzione

Può sembrare un ortodosso in un linguaggio (essenzialmente imperativo) come rubino, ma il mio consiglio è: evitare danni collaterali non aggiornando gli oggetti (tranne se rigorosamente necessario);Crea nuovi nuovi.Paghi un po 'di prestazioni ma riceverai il codice più chiaro, più compatto, più modulare e più facile da eseguire il debug.

http://en.wikipedia.org/wiki/functional_programming

Quindi, nel tuo esempio, basta creare una nuova stringa con un nuovo nome:

complete_name = name + title
.

Altri suggerimenti

Solo un'aggiunta alla risposta del tokland:

approccio funzionale insiste su immutabilità - cioè non alterando gli oggetti esistenti, ma creando un altro quando vuoi per cambiare quello originale. Questo è un po 'contro il paradigma orientato all'oggetto che anche Ruby porta (oggetti mantengono il loro stato internamente, che può essere modificato mediante metodi chiamando su di esso), quindi devi bilanciare un po' tra i due approcci (d'altra parte, beneficiamo Avere più paradigmi facilmente accessibili in una singola lingua).

Allora, tre cose da ricordare per ora:

    .
  1. Impara quale incarico in Ruby è: nient'altro che nominare un oggetto. Quindi, quando dici y=x, stai dicendo solo "Diamo un altro nome y a qualunque cosa sia stato nominato x".
  2. name << title mutate oggetto chiamato name.
  3. name += title accetta oggetti denominati name e generacodictagcode, concatenali in un altro oggetto e assegna che il nuovo nome oggetto title. Non muta nulla.

Ho anche trovato una situazione del genere e ha provocato un bug, che ho preso mezza giornata per capire.Essenzialmente ho fatto qualcosa di simile a questo

hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}
.

Questo codice era all'interno di un loop e nel ciclo, mi aspettavo che la variabile file_name sia di nuovo impostata sul valore originale.Ma l'oggetto.File_Name è stato cambiato, poiché stavo eseguendo file_name.gsub!.Ci sono 2 modi per risolvere questo.Sostituire la chiamata .gsub! con file_name = file_name.gsub o DO file_name = object.file_name.dup.Ho optato per la seconda opzione.

Penso che dovremmo stare attenti con i metodi aventi generatori di generazioneGode e !, poiché cambiano l'oggetto originale su cui stanno agendo, specialmente dopo incarichi come questo.

Un metodo non dovrebbe modificare una variabile (ad esempio utilizzando l'operatore di spostamento) a meno che la sua definizione, la sua definizione lo modificherà.

Allora: MAI modificare un oggetto in un metodo che non ha (A) Crearlo o (B) documento che lo modifica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top