it-swarm.com.de

Beste Ruby-Idiom für "Null oder Null"

Ich suche nach einer prägnanten Möglichkeit, einen Wert zu überprüfen, um zu sehen, ob er null oder null ist. Zur Zeit mache ich so etwas wie:

if (!val || val == 0)
  # Is nil or zero
end

Das scheint aber sehr ungeschickt zu sein.

71
csexton

Objekte haben ein nil? Methode .

if val.nil? || val == 0
  [do something]
end

Oder für nur eine Anweisung:

[do something] if val.nil? || val == 0
65

Wenn Sie Methodennamen mit Fragezeichen am Ende wirklich mögen:


if val.nil? || val.zero?
  # do stuff
end

Ihre Lösung ist gut, wie auch einige andere Lösungen.

Mit Ruby können Sie nach einer hübschen Methode suchen, um alles zu tun, wenn Sie nicht aufpassen.

31
MilesZS

Zunächst einmal denke ich, dass dies die präziseste Methode ist, die Sie für diesen speziellen Zustand prüfen können.

Zweitens ist dies ein Codegeruch, der auf einen möglichen Fehler in Ihrem Design hinweist. Im Allgemeinen sollten Null und Null nicht dasselbe bedeuten. Wenn möglich, sollten Sie versuchen, die Möglichkeit auszuschließen, dass val gleich Null ist, bevor Sie diesen Code schlagen, indem Sie dies entweder am Anfang der Methode oder durch einen anderen Mechanismus überprüfen.

Möglicherweise haben Sie einen absolut legitimen Grund, dies zu tun. In diesem Fall denke ich, dass Ihr Code gut ist, aber ich würde zumindest in Betracht ziehen, den Null-Check nach Möglichkeit zu beseitigen.

29
Mike Deck

Ab Ruby 2.3.0 können Sie den sicheren Navigationsoperator (&.) mit Numeric#nonzero? kombinieren. &. gibt nil zurück, wenn die Instanz nil war, und nonzero? - wenn die Nummer 0 war:

unless val&.nonzero?
  # Is nil or zero
end

Oder postfix:

do_something unless val&.nonzero?
23
ndnenkov

Sie können die Object.nil verwenden? speziell auf null testen (und nicht zwischen falsch und null gefangen werden). Sie können eine Methode auch mit einem Affen-Patch in Object einfügen. 

class Object
   def nil_or_zero?
     return (self.nil? or self == 0)
   end
end

my_object = MyClass.new
my_object.nil_or_zero?
==> false

Dies wird nicht empfohlen, da Änderungen an Object für Kollegen schwer zu verfolgen sind und Ihren Code für andere möglicherweise unvorhersehbar machen.

9
Adrian Dunston

nil.to_i gibt null zurück, daher mache ich das oft:

val.to_i.zero?

Sie erhalten jedoch eine Ausnahme, wenn val ein Objekt ist, das nicht auf #to_i antwortet.

5
ntl

Ich glaube, Ihr Code ist falsch. Es werden drei Werte getestet: nil,falseund null. Dies liegt daran, dass der Ausdruck !val für alle Werte gilt, die falsch sind. In Ruby heißt dies nil und false.

Das Beste, was ich jetzt finden kann, ist

if val == nil || val == 0
  # do stuff
end

Was natürlich nicht sehr schlau ist, ist aber (sehr) klar.

4
unwind

Meine Lösung verwendet auch Verfeinerungen ohne die Bedingungen.

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if val.nothing?
  # Do something
end
3
RichOrElse

Rails führt dies über Attribut-Abfragemethoden aus, wobei 0 und "" neben false und nil auch "false" ergeben. 

if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation

Es hat jedoch seinen Anteil an Kritikern. http://www.joegrossberg.com/archives/002995.html

2
Gishu

Um so idiomatisch wie möglich zu sein, würde ich das vorschlagen.

if val.nil? or val == 0
    # Do something
end

Weil:

  • Es nutzt das Null? Methode.
  • Es verwendet den Operator "oder", der || vorzuziehen ist.
  • Es werden keine Klammern verwendet, die in diesem Fall nicht erforderlich sind. Klammern sollten nur verwendet werden, wenn sie einem bestimmten Zweck dienen, z. B. das Überschreiben bestimmter Operatoren.
2
Joshua Swink

Der kürzeste und beste Weg sollte sein 

if val&.>(0)
  # do something
end

Für val&.>(0)it wird null zurückgegeben, wenn val gleich null ist, da> im Grunde auch eine Methode ist, null ist in Ruby gleich false. Es gibt false zurück, wenn val == 0.

2
user2097847

Kurz und klar

[0, nil].include?(val)

1
Stanislav Kr.

Das ist sehr knapp:

if (val || 0) == 0
  # Is nil, false, or zero.
end

Es funktioniert, solange es Ihnen nichts ausmacht, false genauso zu behandeln wie nil. In den Projekten, an denen ich gearbeitet habe, ist diese Unterscheidung nur gelegentlich von Bedeutung. Die restliche Zeit bevorzuge ich persönlich .nil? und habe etwas kürzeren Code.

[ Update : Ich schreibe so etwas nicht mehr. Es funktioniert, ist aber zu kryptisch. Ich habe versucht, meine Missetaten zu korrigieren, indem ich die wenigen Orte, an denen ich es tat, veränderte.]

Ich habe übrigens .zero? nicht verwendet, da dies eine Ausnahme auslöst, wenn val beispielsweise ein String ist. Aber .zero? wäre in Ordnung, wenn Sie wissen, dass dies nicht der Fall ist.

0
antinome

Anstatt eine Klasse mit Affen zu patchen, können Sie Verfeinerungen verwenden, die in Ruby 2.1 beginnen. Verfeinerungen ähneln dem Affen-Patching; Dadurch können Sie die Klasse ändern, die Änderung ist jedoch auf den Bereich beschränkt, in dem Sie sie verwenden möchten.

Dies ist zu viel, wenn Sie diese Überprüfung einmal durchführen möchten. Wenn Sie sich jedoch wiederholen, ist dies eine gute Alternative zum Affen-Patching.

module NilOrZero
  refine Object do
    def nil_or_zero?
      nil? or zero?
    end
  end
end

using NilOrZero
class Car
  def initialize(speed: 100)
    puts speed.nil_or_zero?
  end
end

car = Car.new              # false
car = Car.new(speed: nil)  # true
car = Car.new(speed: 0)    # true

Verfeinerungen wurden geändert in der letzten Minute, um in die Datei aufgenommen zu werden. So haben frühere Beispiele dies gezeigt, was nicht funktionieren wird.

class Car
  using NilOrZero
end
0
Mohamad

Sie können case verwenden, wenn Sie möchten:

 case val with nil, 0
      # do stuff
 end

Dann können Sie alles verwenden, was mit === funktioniert, was manchmal schön ist. Oder machen Sie so etwas:

not_valid = nil, 0
case val1 with *not_valid
      # do stuff
 end
 #do other stuff
 case val2 with *not_valid, false    #Test for values that is nil, 0 or false
      # do other other stuff
 end

Es ist nicht gerade eine gute OOP, aber es ist sehr flexibel und funktioniert. Meine ifs enden normalerweise cases.

Natürlich funktioniert auch Enum.any?/Enum.include? ... wenn Sie wirklich kryptisch werden möchten:

if [0, nil].include? val
    #do stuff
end

Das Richtige ist natürlich, eine Methode oder Funktion zu definieren. Wenn Sie mit vielen Werten dasselbe tun müssen, verwenden Sie eine Kombination dieser Nice-Iteratoren.

0
martin

Dies ergibt für null und null den Wert true: nil.to_s.to_d == 0

0
Sam
unless (val || 0).zero?

    # do stufff

end
0
Abel

Ich mag die Rails blank?-Methode für diese Art von Dingen wirklich, aber es wird keine true für 0 zurückgegeben. So können Sie Ihre Methode hinzufügen:

def nil_zero? 
  if respond_to?(:zero?) 
    zero? 
  else 
    !self 
  end 
end 

Und es wird geprüft, ob irgendein Wert Null oder 0 ist:

nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false

if val.nil_zero?
  #...
end
0
klew

Ich gehe damit um, indem ich ein "ist?" Methode, die ich dann auf verschiedenen Klassen unterschiedlich implementieren kann. Also für Array "ist?" bedeutet "Größe> 0"; für Fixnum bedeutet es "Selbst! = 0"; für String bedeutet es "self! = ''". NilClass definiert natürlich "ist?" als gerade Null zurückkehren.

0
glenn mcdonald