Rubino: se variabile vs se variabile.nil?


11

Sono nuovo di Ruby e sono rimasto sorpreso quando ho scoperto che tutti gli oggetti sono veri a parte zero e falso. Anche 0 è vero.

Una cosa bella di quella proprietà della lingua è che puoi scrivere:

if !variable
  # do stuff when variable is nil
end

I miei colleghi, che sono sviluppatori Ruby più esperti, insistono sul fatto che dovrei scegliere quello invece di usare .nil? così:

if variable.nil?
  # do stuff when variable is nil
end

Tuttavia, credo che quest'ultima sia un'opzione migliore per due motivi: 1. Penso che sia più orientata agli oggetti, specialmente in un linguaggio come Ruby in cui tutto è uno scambio di oggetti e messaggi. 2. È più leggibile, a mio avviso, anche se è meno compatto.

Sto commettendo un errore "newbie" qui?


4
Stai testando per zero? o un valore falso?

Sto testando per zero. Fondamentalmente se la variabile è nulla, faccio qualcosa (o no)
Javier Holguera

3
Se stai testando per zero, perché vuoi che anche il test per false entri in quel blocco?

D'accordo, l'ho sottolineato come un altro motivo per preferire .nil? Ma hanno insistito sul fatto che "se la variabile fa x" è più idiomatica di "se variabile.nil? Do x" e preferibile quando sai che quella variabile non è booleana
Javier Holguera,

Risposte:


17

Scrivi quello che vuoi dire. Intendi quello che scrivi.

Facciamo un test diverso. .vowel?

if char == 'a'
   # do stuff
end

vs

if char.vowel?
   # do stuff
end

Ora, è ovvio che questi non fanno la stessa cosa. Ma se ti aspetti solo chardi essere ao bfunzionerà. Ma confonderà il prossimo sviluppatore: il secondo blocco verrà inserito per le condizioni in cui si trova [eiou]anche char . Ma per a, funzionerà correttamente.

Sì, è questo il caso nile falsesono gli unici valori falsi in Ruby. Tuttavia, se stai testando niltestando per nil || false, questo non è ciò che intendi.

Significa che il prossimo sviluppatore (che sembra essere un folle omicidio di ascia che conosce il tuo indirizzo di casa) leggerà il codice e si chiederà perché falsedovrebbe entrare anche lì.

Scrivi il codice che trasmette esattamente ciò che intendi.


3

Considera quanto segue:

response = responses.to_a.first

Ciò restituirà il primo elemento di responses, o nil. Quindi perché le dichiarazioni condizionali trattano nilcome falsepossiamo scrivere:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

Che è più leggibile di:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

Il if (object)modello è molto comune nel codice Ruby. Porta anche bene al refactoring, ad esempio:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Ricorda anche che un metodo Ruby ritorna nildi default. Così:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

può essere semplificato per:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Quindi possiamo ulteriormente refactoring:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Ora puoi sostenere che tornare nilnon è sempre la migliore idea, dal momento che significa controllare nilovunque. Ma questo è un altro bollitore di pesce. Dato che testare la "presenza o assenza" di oggetti è un requisito così frequente, la verità degli oggetti è un aspetto utile di Ruby, sebbene sorprendente per i neofiti della lingua.


2

Non solo viene if variable.nil?letto più come un linguaggio naturale, ma protegge anche da un programmatore che gli assegna accidentalmente un falsevalore e cade nella tua ifaffermazione, dal momento che Ruby è un linguaggio vagamente tipizzato.


1
Quindi il commento iniziale nella domanda originale era sbagliato? Avrebbe dovuto essere "fare cose quando la variabile è nulla o falsa"? E poiché il codice che non corrisponde al commento è un bug, c'è subito un bug?
gnasher729,

Corretta. Un semplice test di verità potrebbe introdurre errori logici.
Greg Burghardt,

0

Idiomaticamente, unless variableè preferibile if !variable. Le ifdichiarazioni negate sono spesso considerate un odore di codice poiché è più facile perdere la negazione durante lo skimmer.

L'immagine più grande qui è che fare nilcontrolli come questo è anche un po 'un odore di codice. Per una corretta OO, mira a utilizzare il modello di oggetti null in modo che questo tipo di controllo non sia mai necessario. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Dì agli oggetti cosa fare, non chiedere loro cosa sono. Questo a volte è noto come dire non chiedere

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.