Ruby: se variabile vs if variable.nil?

9

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

Una cosa carina di questa proprietà della lingua è che puoi scrivere:

if !variable
  # do stuff when variable is nil
end

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

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

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

Sto facendo un errore "newbie" qui?

    
posta Javier Holguera 13.11.2015 - 20:15
fonte

4 risposte

16

Scrivi cosa intendi. Significa ciò 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 char come a o b , funzionerà. Ma confonderà il prossimo sviluppatore - il secondo blocco verrà inserito per le condizioni in cui il char è [eiou] anche. Ma per a , funzionerà correttamente.

Sì, è il caso che nil e false siano gli unici valori falsy in Ruby. Tuttavia, se stai testando per nil testando per nil || false , questo non è ciò che intendi.

Significa che il prossimo sviluppatore (che capita di essere un pazzo assassino che conosce il tuo indirizzo di casa) leggerà il codice e si chiederà perché false dovrebbe andare anche lì.

Scrivi il codice che esattamente cosa intendi.

    
risposta data 13.11.2015 - 20:30
fonte
3

Considera quanto segue:

response = responses.to_a.first

Questo restituirà il primo elemento di responses o nil . Quindi, poiché le istruzioni condizionali trattano nil come false possiamo 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 modello if (object) è 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 restituisce nil per impostazione predefinita. Quindi:

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

può essere semplificato in:

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 affermare che restituire nil non è sempre l'idea migliore, poiché significa controllare per nil ovunque. Ma quello è un altro bollitore di pesce. Dato che il test per la presenza o assenza di oggetti è un requisito così frequente, la verità degli oggetti è un aspetto utile di Ruby, anche se è sorprendente per i neofiti del linguaggio.

    
risposta data 21.11.2015 - 00:13
fonte
2

Non solo if variable.nil? legge più come un linguaggio naturale, ma protegge anche da un programmatore assegnandogli accidentalmente un valore false e cade nella tua istruzione if , dal momento che Ruby è un linguaggio con caratteri generici.

    
risposta data 15.11.2015 - 02:31
fonte
0

Idiomaticamente, unless variable è preferibile a if !variable . Le dichiarazioni di if negate sono spesso considerate un odore di codice in quanto è più facile perdere la negazione durante la schiumatura.

L'immagine più grande qui è che facendo nil assegni come questo è anche un po 'di odore di codice. Per OO corretto, mirare a utilizzare il modello di oggetto nullo in modo che questo tipo di controllo non sia mai necessario. link

Dì agli oggetti cosa fare, non chiedere loro cosa sono. Questo è talvolta noto come tell non chiedere

    
risposta data 23.11.2015 - 13:34
fonte

Leggi altre domande sui tag