2013-09-03 6 views
6

Le code suivant utilise un opérateur de bascule.Pourquoi un opérateur Flip-Flop inclut-il la deuxième condition?

(1..10).each {|x| print "#{x}," if x==3..x==5 } 

Pourquoi les résultats 3,4,5?

Je pense qu'il devrait être 3,4.

Comme mentionné dans un tutoriel, cette expression devient vraie quand x == 3, et continue à être vrai jusqu'à x == 5. Comment '5' a-t-il pu être imprimé s'il est faux? Quelqu'un pourrait-il clarifier cela pour moi?

+0

lien la documentation s'il vous plaît .. –

+3

Vous avez répondu à votre propre question. 'et continuer à être vrai jusqu'à x == 5' – MurifoX

+0

mais quand x devient 5, il est faux droit? Comment est-ce que 5 pouvait être imprimé? – bean

Répondre

0

Vous recherchez une gamme exclusive? Vous pouvez utiliser trois points et la méthode cover?.

(1..10).each { |x| print "#{x}," if (3...5).cover?(x) } 

La raison pour laquelle il imprime 3,4,5, dans votre exemple est parce qu'il dit que si x est dans la plage de 3 à 5 print il.

0

Pour clarifier le commentaire par @MififoX, La bascule est vraie jusqu'à x==5, et donc vrai spécifiquement quand x==5, mais est faux chaque fois que l'expression est évaluée après cela. Ainsi vous voyez toujours 5 être imprimé.

+0

merci, c'est raisonnable. – bean

4

Le lien important, de "Le langage de programmation Ruby" est:

4.6.9.1 Boolean flip-flops

Quand les .. et ... les opérateurs sont utilisés dans une condition, comme une instruction if, ou dans une boucle, comme une boucle while (voir Chapitre 5 pour plus d'informations sur les conditionnelles et les boucles), ils ne créent pas d'objets Range. Au lieu de cela, ils créent un type spécial d'expression booléenne appelé une bascule. Une expression flip-flop est évaluée à true ou false, exactement comme le font les expressions de comparaison et d'égalité . La chose extraordinairement inhabituelle au sujet d'une expression de bascule , cependant, est que sa valeur dépend de la valeur de l'évaluation précédente ations. Cela signifie qu'une expression de bascule a un état qui lui est associé; il doit se souvenir des informations sur les évaluations précédentes. Parce qu'il a l'état, vous attendez une bascule d'être un objet d'une certaine sorte. Mais ce n'est pas-c'est une expression Ruby, et l'interpréteur Ruby stocke l'état (juste une valeur booléenne) qu'il requiert dans sa représentation interne analysée de l'expression.

Dans ce contexte, considérons la bascule dans le code suivant. Notez que le premier .. dans le code crée un objet Range. Le second crée la bascule expression :

(1..10).each {|x| print x if x==3..x==5 } 

La bascule se compose de deux expressions booléennes jointe à l'opérateur .., dans le cadre d'une conditionnelle ou de la boucle. Une expression de bascule est fausse à moins que et jusqu'à ce que l'expression de gauche évalue à vrai. Une fois que cette expression est devenue vraie, l'expression «retourne» dans un état vrai persistant. Il reste dans cet état et les évaluations ultérieures retournent true jusqu'à ce que l'expression de droite ait la valeur true.Lorsque ce se produit, la bascule "revient" à un état faux persistant. Les évaluations suivantes de l'expression renvoient false jusqu'à ce que l'expression de gauche redevienne true. Dans l'exemple de code, la bascule est évaluée à plusieurs reprises, pour des valeurs de x de 1 à 10. Elle commence à l'état faux, et est évaluée à faux lorsque x est 1 et 2. Lorsque x == 3, le flip-flop retourne à true et retourne vrai. Il continue à renvoyer vrai lorsque x est 4 et 5. Lorsque x == 5, cependant, la bascule retourne à false, et renvoie false pour les valeurs restantes de x. Le résultat est que ce code imprime 345.

3

.. ou flip-flop est hérité de Perl qui l'a obtenu de AWK et sed dans * nix. C'est très puissant, mais dans votre usage particulier c'est assez obscur et pas un bon choix pour la logique que vous voulez, surtout dans Ruby. Au lieu d'utiliser:

(1..10).each {|x| puts x if (3..5) === x } 

qui délivre en sortie:

3 
4 
5 

Cela dit, il est extrêmement puissant quand vous avez besoin d'extraire une gamme de lignes à partir d'un fichier:

File.foreach('/usr/share/dict/propernames') { |li| puts li if ($. == 5 .. $. == 7) } 

qui sort:

Agatha 
Ahmed 
Ahmet 

Pe rl permet une expression encore plus laconique en utilisant uniquement les numéros de ligne de la ligne actuellement lue (AKA $.) mais Ruby ne supporte pas cela.

Il y a aussi la possibilité d'utiliser des expressions régulières, qui se comportent de la même que la comparaison précédente:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^Wa/] .. li[/^We/]) } 

qui sort:

Wade 
Walt 
Walter 
Warren 
Wayne 
Wendell 

Parce que le travail regex, il est possible de créer un motif complexe récupérer les lignes d'un fichier basé sur des correspondances. En tant que premier, puis déclencheur du second modèle, les lignes sont capturées. Si, plus tard dans le fichier, une autre ligne déclenche le premier motif, la capture se produira à nouveau jusqu'à ce que le second motif corresponde. Il est merveilleusement puissant:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (
    li[/^Am/] .. li[/^An/] or 
    li[/^Wa/] .. li[/^We/] 
) 
} 

qui sort:

Amanda 
Amarth 
Amedeo 
Ami 
Amigo 
Amir 
Amos 
Amy 
Anatole 
Wade 
Walt 
Walter 
Warren 
Wayne 
Wendell 

Ou alternativement, pour nos amis parlant obscur de code:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^(?:Am|Wa)/] .. li[/^(?:An|We)/]) } 
1

Je trouve un morceau de code pour illustrer comment le flip-flop fonctionne (juste dans le même livre où ce morceau de code apparaît, j'espère que ça aide pour ceux qui ont la même question que moi)

$state = false # Global storage for flip-flop state 
    def flipflop(x) # Test value of x against flip-flop 
     if !$state # If saved state is false 
      result = (x == 3) # Result is value of lefthand operand 
      if result # If that result is true 
       $state = !(x == 5) # Then saved state is not of the righthand operand 
      end 
      result # Return result 
     else # Otherwise, if saved state is true 
      $state = !(x == 5) # Then save the inverse of the righthand operand 
      true # And return true without testing lefthand 
     end 
    end 
0

Une expression bascule est évaluée à vrai ou faux, tout comme les expressions de comparaison et de l'égalité font. La chose extraordinairement inhabituelle au sujet d'une expression de bascule, cependant, est que sa valeur dépend de la valeur des évaluations précédentes. Cela signifie qu'une expression de bascule a un état qui lui est associé; il doit se souvenir des informations sur les évaluations précédentes.Parce qu'il a l'état, vous attendez une bascule d'être un objet d'une certaine sorte. Mais ce n'est pas-c'est une expression Ruby, et l'interpréteur Ruby stocke l'état (juste une valeur booléenne) qu'il requiert dans sa représentation interne analysée de l'expression. Avec ce contexte en tête, considérons la bascule dans le code suivant. Notez que le premier ".." dans le code crée un objet Range. Le second crée l'expression bascule:

(1..10).each {|x| print x if x==3..x==5 } 

La bascule se compose de deux expressions booléennes jointes avec le .. opérateur, dans le cadre d'une conditionnelle ou de la boucle. Une expression de bascule est fausse à moins que et jusqu'à ce que l'expression de gauche évalue à vrai. Une fois que cette expression est devenue vraie, l'expression "retourne" dans un état vrai persistant. Il reste dans cet état et les évaluations ultérieures retournent la valeur true jusqu'à ce que l'expression de droite ait la valeur true. Lorsque ce se produit, la bascule "revient" à un état faux persistant. Les évaluations suivantes de l'expression renvoient false jusqu'à ce que l'expression de gauche redevienne true. Dans l'exemple de code, la bascule bistable est évaluée de manière répétée, pour des valeurs de x comprises entre 1 et 10. Elle commence à l'état faux et est évaluée à faux lorsque x vaut 1 et 2. Lorsque x == 3, la bascule retourne à vrai et retourne vrai. Il continue à renvoyer vrai lorsque x est 4 et 5. Lorsque x == 5, cependant, la bascule retourne à false, et retourne false pour les valeurs restantes de x. Le résultat est que ce code imprime 345.

Questions connexes