Ruby: Verwenden des Schlüsselwortes "unless" mit einer return-Anweisung

Ich arbeite gerade an einem Projekt, bei dem ich Code habe, der so aussieht:

  # the first return is the one causing problems
  def collect
    return Hash["IdentANode", Array[@id, ",", @ident_a_node.collect]] unless @ident_a_node.nil? and @id.nil?
    return Hash["IdentANode", @id] unless @id.nil?
  end

Wo verwende ich den Operator außer, um die Rückgabeanweisung bedingt auszuführen. Aus irgendeinem Grund wird dieser Code immer noch ausgeführt, selbst wenn @ident_a_node nil ist. Bei der Ausführung bekomme ich diese Nachricht:

IdentANode.rb: 14: in collect ': undefinierte Methode collect' für   nil: NilClass (NoMethodError)

Das verwirrt mich, weil ich gedacht hatte, dass das Schlüsselwort außer es verhindern würde. Wenn ich die Anweisung in dieses Formular ändere:

if not @ident_a_node.nil? and not @id.nil?
  return Hash["IdentANode", Array[@id, ",", @ident_a_node.collect]]
end  

oder diese Form:

return Hash["IdentANode", Array[@id, ",", @ident_a_node.collect]] if not @ident_a_node.nil? and not @id.nil?

Die return-Anweisung wird nicht ausgeführt, was gibt es? Warum gibt es einen Unterschied zwischen diesen beiden Aussagen? Sind mehrere Bedingungen mit dem Schlüssel , außer , problematisch?

Irgendwelche Ideen würden geschätzt werden

0
hinzugefügt bearbeitet
Ansichten: 1

2 Antworten

Du hast einen logischen Fehler drin. Sie testen, dass sie beide nil sind, damit sie beim Testen nicht ausgeführt werden, wenn entweder nil . Wahrscheinlich haben Sie sich selbst in diese Situation gebracht, indem Sie zu viele Ebenen der Negation haben. Alles mehr als eins ist inakzeptabel.

Mit anderen Worten, Sie können mit "wenn es nicht regnet" durchkommen, aber sollten keine Dinge wie "verwenden, außer wenn das Flag is_not_raining nicht auf die Umkehrung von false gesetzt ist".

Meine persönliche Meinung ist, dass Trailing-Bedingungen nicht verwendet werden sollten, es sei denn, es ist offensichtlich, dass sie vorhanden sind. Wie Sie in Ihrem Beispiel sehen können, müssen Sie horizontal scrollen, um die Bedingung zu finden, und wichtige Informationen vor dem Entwickler verbergen.

Als Stil verwenden Sie nicht nicht , wenn ! den gleichen Job ausführt. Zweitens testen Sie speziell gegen nil , wenn Sie wahrscheinlich nur einen bestimmten Wert haben möchten.

Andere Probleme umfassen die Verwendung von Hash [] und Array [] , die sicher Artefakte der Verwendung einer Sprache sind, die sie benötigt. ruby erlaubt, wie JavaScript, eine implizite Deklaration dieser mit {} bzw. [] .

Eine richtige Ruby-Version Ihres Codes ist:

if (@ident_a_node and @id)
  return { "IdentANode" => [ @id, ",", @ident_a_node.collect ] }
end  
0
hinzugefügt
@NiklasB. Ich stimme zu, dass die Ausführlichkeit von Sprachen wie Java ein riesiger Nachteil ist, aber es ist ein harter Übergang für mich, alles, was ich über Programmierung weiß, kommt von diesem Paradigma der Ausführlichkeit
hinzugefügt der Autor Hunter McMillen, Quelle
Danke, das war sehr hilfreich.
hinzugefügt der Autor Hunter McMillen, Quelle
Was ich in der Collect-Methode mache, ist das Zurückgeben eines Hash. Wenn der Wert also null ist, sollte der Hash mit einem Nullwert zurückgegeben werden. {"IdentANode" => nil}
hinzugefügt der Autor Hunter McMillen, Quelle
Der Hauptgrund, den ich verwende, ist, weil ich viele dieser Bedingungen habe und eine if-Anweisung für jeden würde den Code meiner Meinung nach unordentlicher machen.
hinzugefügt der Autor Hunter McMillen, Quelle
Gibt es auch einen guten Style-Guide für Dinge wie und Array [] vs {key => value} und [] ??
hinzugefügt der Autor Hunter McMillen, Quelle
@NiklasB. Der Großteil meiner Programmiererfahrung stammt aus Java und C, für Java und C existieren keine Literale
hinzugefügt der Autor Hunter McMillen, Quelle
@ Hunter: Ich denke, das ist kein allzu großes Problem. Die meisten dieser Sprachen basieren auf ein bis drei sehr grundlegenden Datenstrukturen, die dann in jeder Anwendung sehr umfangreich genutzt werden. Für ruby sind das Arrays, Hashes und vielleicht Symbole (ich habe hier keine Strings angegeben, weil man von Java an ihre Syntax gewöhnt sein sollte). Wenn Sie wissen, wie und wann Sie diese verwenden, ist es ein einfacher Übergang :)
hinzugefügt der Autor Niklas B., Quelle
@Hunter: Nun, das machen sie in den meisten modernen Sprachen, wie JavaScript, Python, LISP (Clojure, Scheme, CL, ...), Scala, Haskell, ... Eigentlich ist C sehr low-level, es hat keinen eingebauten in Datenstrukturen mit Ausnahme von Arrays (für die die Initialisierungssyntax existiert). Die Tatsache, dass Java so etwas nicht hat, ist ein riesiges Problem, IMHO (aber es hat auch die new int [] {1, 2, 3} Sache).
hinzugefügt der Autor Niklas B., Quelle
@Hunter: Ist es nicht offensichtlich, dass Literale sauberer sind als explizite Konstruktoren, wenn sie verfügbar sind? Was den allgemeinen Ruby-Stil angeht, mag ich die Github-Ruby-Richtlinien
hinzugefügt der Autor Niklas B., Quelle
Warum gibt zurück? Ich würde nur tun, wenn ...; [Ausdruck]; sonst; Null; end (um klarzustellen, dass nil im Falle eines Fehlers zurückgegeben wird)
hinzugefügt der Autor Niklas B., Quelle

Benutze es nur mit und/oder, es ist einfach nur verwirrend. es sei denn @ ident_a_node.nil? und @ id.nil? bedeutet wenn! (@ ident_a_node.nil? und @ id.nil?) , was bedeutet, dass es immer dann zurückkehrt, wenn eine der beiden Instanzvariablen nicht null ist.

if !(@ident_a_node.nil? and @id.nil?)

ist das gleiche wie

if [email protected]_a_node.nil? or [email protected]?

was es noch deutlicher machen sollte, warum es nicht so ist wie

if not @ident_a_node.nil? and not @id.nil?
0
hinzugefügt
Aus irgendeinem Grund habe ich eine Übersetzung wie folgt erwartet: if! first_condition und! second_condition Vielen Dank
hinzugefügt der Autor Hunter McMillen, Quelle
Ich habe versucht mit außer die Art und Weise @ NiklasB. Ratschläge, das gleiche Problem bleibt. , außer ist knifflig.
hinzugefügt der Autor iGbanam, Quelle
Eigentlich finde ich es am liebsten, weil es dieselbe Semantik wie ein assert hat. Grundsätzlich können wir den return außer mit assert oder ArgumentError, "..." außer jederzeit austauschen.
hinzugefügt der Autor Niklas B., Quelle
@Yasky: Ich verstehe was du meinst. OP bedeutet wahrscheinlich return außer @ident_a_node und @id . Keine Notwendigkeit, nil? zu verwenden (ich muss es gelesen haben). Ich betrachte diesen Reiniger als die äquivalente return if @ ident_a_node.nil? oder @ id.nil?
hinzugefügt der Autor Niklas B., Quelle
@dominik: , es sei denn erlaubt es Ihnen, Ihre Bedingungen in einfacher Sprache auszudrücken. Darüber hinaus ist der return es sei denn ist ein Idiom, das ich ziemlich oft sehe, so dass es mir auffällt, dass viele Leute daran gewöhnt sind. Um ehrlich zu sein, sehe ich solche Arten boolescher Fehler sehr selten von erfahrenen Entwicklern, weshalb ich es nicht als verwirrend empfinde.
hinzugefügt der Autor Niklas B., Quelle
@Hunter: Wenn es um die Negation von Konjunktion und Disjunktion geht, sind De Morgans Gesetze sehr hilfreich.
hinzugefügt der Autor Niklas B., Quelle
@NiklasB. Wenn man bedenkt, dass der OP-Fehler ein sehr häufiges ist, würde ich es für verwirrend genug halten, um es zu vermeiden :) Es gibt keinen Grund, warum wir De Morgan immer dann in unserem Kopf anwenden sollten, wenn wir mit oder ohne sehen. Es gibt auch keinen Nutzen für die Verwendung, außer hier.
hinzugefügt der Autor Dominik Honnef, Quelle