2010-07-30 7 views
3

Il y avait deux bonnes raisons pour lesquelles Ruby 1.8 ne prennent pas en charge certains types de surcharge comme ||/or, &&/and, !/not, ?::Pourquoi Ruby 1.9 permet le dépassement! ! =! ~?

  • sémantique de court-circuit ne peuvent pas être mises en œuvre avec des méthodes en Ruby sans changements très étendus à la langue.
  • Ruby est codé en dur pour traiter seulement nil et false comme faux dans des contextes booléens.

La première raison ne concerne pas !/not mais la deuxième fait encore. Ce n'est pas comme si vous pouviez introduire vos propres types d'objets de type booléen en utilisant seulement ! alors que &&/|| sont toujours codés en dur. Pour d'autres utilisations, il existe déjà un opérateur de complémentarité ~ avec &/|.

Je peux imaginer qu'il ya beaucoup de code attendant !obj être synonyme de obj ? false : true et !!obj avec obj ? true : false - Je ne suis même pas sûr de savoir comment est le code censé traiter des objets qui évaluent à true dans le contexte booléen, mais ! à quelque chose de non-faux.

Il ne semble pas que Ruby envisage d'introduire un support pour d'autres fausses valeurs. Rien dans Ruby stdlib semble remplacer ! donc je n'ai trouvé aucun exemple.

Est-ce qu'il y a un très bon usage qui me manque?

Répondre

1

Auto-réponse. J'ai trouvé un usage un peu raisonnable jusqu'à présent. Je peux pirater cela fonctionne en 1.9.2 en quelques lignes:

describe "Mathematics" do 
    it "2 + 2 != 5" do 
    (2+2).should != 5 
    end 
end 

Avant Ruby 1.9.2 cela se traduit:

describe "Mathematics" do 
    it "2 + 2 != 5" do 
    ((2+2).should == 5) ? false : true 
    end 
end 

Mais comme valeur de retour est jeté loin nous n'avons pas les moyens de distinguer == 5 de != 5 à court de demander à Ruby pour l'arbre d'analyse de bloc. PositiveOperatorMatcher#==(5) soulèverait simplement ExpectationNotMetError exception et ce serait le cas. Il semble should !~ /pattern/, should !be_something etc. peut également être fait pour travailler.

Ceci est une amélioration par rapport à (2+2).should_not == 5, mais pas vraiment un gros problème. Et il n'y a aucun moyen de le pirater davantage pour obtenir des choses comme (2+2).should be_even or be_odd.

Bien sûr, la bonne chose à faire ici serait asking Ruby for parse tree and macro-expanding that. Ou en utilisant des crochets de débogage dans l'interpréteur Ruby. Y a-t-il des cas d'utilisation meilleurs que celui-ci? Par ailleurs, il ne suffirait pas d'autoriser les remplacements pour ! en traduisant !=/!~ à l'ancienne. Pour !((2+2).should == 5) pour travailler #== ne peut pas déclencher une exception avant que ! soit appelée. Mais si #== échoue et ! ne se lance pas l'exécution continuera simplement. Nous serons en mesure de signaler que l'assertion a échoué après les sorties du bloc, mais au coût de l'exécution du test après le premier échec.(sauf si nous activons les hooks de débogage de ruby ​​juste après l'assertion échouée pour voir si l'appel de méthode suivant est !self, ou quelque chose comme ça)

Questions connexes