2013-09-03 9 views
6

Następujący kod używa operatora przerzucania.Dlaczego operator Flip-flop uwzględnia drugi warunek?

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

Dlaczego są wyniki 3,4,5?

Myślę, że powinno być 3,4.

Jak wspomniano w samouczku, to wyrażenie staje się prawdziwe, gdy x == 3, i nadal jest prawdziwe do x == 5. W jaki sposób wydrukowano "5", jeśli wynik jest fałszywy? Czy ktoś mógłby mi to wyjaśnić?

+0

link dokumentacji proszę .. –

+3

Odpowiedziałeś na własne pytanie. 'i nadal są prawdziwe, dopóki x == 5' – MurifoX

+0

, ale kiedy x stanie się 5, to jest fałszywe prawda? jak wtedy można wydrukować 5? – bean

Odpowiedz

0

Szukasz ekskluzywnego asortymentu? Możesz użyć trzech kropek i metody cover?.

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

Powodem drukuje 3,4,5, w swojej przykład dlatego, że mówi, że jeśli x jest w zakresie od 3 do 5 wydrukować.

0

Aby wyjaśnić komentarz przez @MurifoX, Przerzutnik jest prawdą aż x==5, a więc prawdą szczególnie gdy x==5, ale za każdym razem jest fałszywe wyrażenie ocenia się po tym. W ten sposób nadal drukowane jest 5.

+0

dzięki, to jest uzasadnione. – bean

4

Ważną link z "The Ruby Programming Language" jest:

4.6.9.1 Boolean flip-flops

Gdy .. i ... Operatorzy są wykorzystywane w ramach warunkowego, takich jak if, lub w pętli, na przykład pętli while (więcej informacji na temat warunków i pętli warunkowych, patrz Rozdział 5), nie tworzą obiektów Range. Zamiast tego tworzą specjalny rodzaj wyrażenia Boolean zwanego flip-flop. Wyrażenie "flip-flop" zwraca wartość "prawda" lub "fałsz", tak samo jak wyrażenia porównania i równości. Niezwykle niezwykłą rzeczą w wyrażeniu typu "flip-flop" jest to, że jego wartość zależy od wartości poprzedniej wartości - . Oznacza to, że wyrażenie flip-flop ma stan powiązany z tym; musi zapamiętać informacje o poprzednich ocenach. Ponieważ ma on stan, będziesz oczekiwał, że flip-flop będzie obiektem jakiegoś rodzaju. Ale to nie jest - jest to wyrażenie w języku Ruby, a interpreter Ruby przechowuje stan (tylko jedną wartość logiczną), którego wymaga w swojej wewnętrznej analizie składniowej wyrażenia.

Mając to na uwadze, rozważ flip-flop w poniższym kodzie. Zauważ, że pierwsze .. w kodzie tworzy obiekt Range. Drugi tworzy przerzutnika wyrażenie:

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

Przerzutnik składa się z dwóch wyrażeń logiczne połączone z operatorem .. W kontekście warunkowego lub pętli . Wyrażenie typu "flip-flop" jest fałszywe, chyba że do momentu, w którym wyrażenie "lefthand" zostanie ocenione jako prawdziwe. Kiedy to wyrażenie stanie się prawdziwe, naciśnięcie "przerzuci" w stały stan rzeczywisty. Pozostaje w tym stanie, a kolejne oceny zwracają wartość true, dopóki prawe wyrażenie nie zwróci wartości true.Kiedy to się stanie, przerzutnik "przerzuci" z powrotem do trwałego stanu fałszywego. Kolejne oceny wyrażenia zwracają fałsz, dopóki lewe wyrażenie nie stanie się ponownie prawdziwe. W przykładowym kodzie przerzutnik jest oceniany wielokrotnie, dla wartości od x od 1 do 10. Zaczyna się w stanie fałszywym, a wartość false oznacza, że ​​x wynosi 1 i 2. Gdy x == 3, flip-flop zmienia się w true i zwraca true. Wciąż zwraca wartość true, gdy x jest równe 4 i 5. Kiedy x == 5, flip-flop powraca do wartości false i zwraca false dla pozostałych wartości x. Powoduje to, że ten kod drukuje 345.

3

.. lub flip-flop jest dziedziczone z Perla, który dostał go od AWK i sed w * nix. Jest bardzo potężny, ale w twoim konkretnym zastosowaniu jest dość mało znany i nie jest dobrym wyborem dla logiki, którą chcesz, szczególnie w Ruby. Zamiast używać:

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

które wyjścia:

3 
4 
5 

Powiedział, że jest to bardzo silny, gdy trzeba wyodrębnić zakres wierszy z pliku:

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

które wyjścia:

Agatha 
Ahmed 
Ahmet 

Pe rl pozwala na jeszcze bardziej wyraziste wyrażenie, używając tylko numerów linii aktualnie czytanej linii (AKA $.), ale Ruby nie obsługuje tego.

Istnieje również możliwość korzystania z wyrażeń regularnych, które zachowują się podobnie jak poprzedni porównania:

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

które wyjścia:

Wade 
Walt 
Walter 
Warren 
Wayne 
Wendell 

Ponieważ regex pracy, to jest możliwe, aby utworzyć złożony wzór do pobierz linie z pliku na podstawie dopasowań. Jako pierwszy, a następnie drugi spust schematu, linie są przechwytywane. Jeśli później w pliku kolejna linia wyzwoli pierwszy wzorzec, przechwytywanie pojawi się ponownie, dopóki drugi wzór nie pasuje. To cudownie potężny:

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

które wyjścia:

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

lub na przemian, na naszych niejasne kodowych języcznych przyjaciół:

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

znajdę kawałek kodu, aby zilustrować jak flip-flop działa (tylko w tej samej książce, w której pojawia się ten fragment kodu, mam nadzieję, że pomaga on tym, którzy mają takie samo pytanie jak ja)

$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

Wyrażenie przerzutnik wartość true lub false, tak jak porównania i równość wyrażenia zrobić. Niezwykle niezwykłą rzeczą w wyrażeniu typu flip-flop jest jednak to, że jego wartość zależy od wartości poprzednich ocen. Oznacza to, że wyrażenie flip-flop ma stan powiązany z tym; musi pamiętać informacje o poprzednich ocenach.Ponieważ ma on stan, będziesz oczekiwał, że flip-flop będzie obiektem jakiegoś rodzaju. Ale to nie jest - jest to wyrażenie w języku Ruby, a interpreter Ruby przechowuje stan (tylko jedną wartość logiczną), którego wymaga w swojej wewnętrznej analizie składniowej wyrażenia. Mając to na uwadze, rozważ flip-flop w poniższym kodzie. Zauważ, że pierwsze ".." w kodzie tworzy obiekt Range. Drugi tworzy ekspresję przerzutnika:

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

Przerzutnik składa się z dwóch wyrażeń logicznych połączonych z operatorem .. W kontekście warunkowego lub pętli . Wyrażenie typu "flip-flop" jest fałszywe, chyba że do momentu, w którym wyrażenie "lefthand" zostanie ocenione jako prawdziwe. Kiedy to wyrażenie staje się prawdziwe, wyrażenie "przerzuca" na stały stan prawdziwy. Pozostaje w tym stanie, a kolejne oceny zwracają wartość true, dopóki prawe wyrażenie nie zwróci wartości true. Kiedy to się stanie, przerzutnik "przerzuci" z powrotem do trwałego stanu fałszywego. Kolejne oceny wyrażenia zwracają fałsz, dopóki lewe wyrażenie nie stanie się ponownie prawdziwe. W przykładowym kodzie przerzutnik jest oceniany wielokrotnie, dla wartości od x od 1 do 10. Zaczyna się w stanie fałszywym, a wartość false oznacza, że ​​x wynosi 1 i 2. Kiedy x == 3, flip-flop przechodzi na true i zwraca true. Wciąż zwraca wartość true, gdy x to 4 i 5. Kiedy x == 5, flip-flop powraca do wartości false i zwraca wartość false dla pozostałych wartości x. W rezultacie kod ten drukuje 345.

Powiązane problemy