Quando os operadores .. e ... são usados em condicionais eles não criam objetos Range, mas sim, criam um tipo especial de expressão Boolean: flip-flop. Tanto o operador da esquerda, quanto o da direita devem ser expressões Boolean. Como é de se esperar um flip-flop retorna true ou false, mas esse valor depende da iteração anterior, assim, uma expressão flip-flop armazena um estado.
Funcionamento de uma expressão flip-flop
Vamos a um exemplo:
(1..10).each {|x| print x if x==3..x==5 }
Aqui, a flip-flop consiste nas duas condições (x==3 e x==5) ligadas pelo operador .. na condicional if no final.
A expressão é false até que a expressão da esquerda se torne true, então a expressão dá um “flip” e mantém o estado true. Ela se mantém true (e retorna sempre true) até que a expressão da direita se torne true, assim a expressão dá um “flop” para um estado false até que a esquerda se torne true novamente e sucessivamente.
Com isso em mente, o exemplo acima imprime: 345
Uma flip-flop pode ser escrito tanto com .. quanto com ...: quando uma flip-flop .. torna-se true, ele retorna true e também testa logo em seguida a expressão da direita para ver se deve mudar o estado para false. Já uma flip-flop ... espera pela próxima iteração antes de testar a expressão da direita.
Exemplo:
# Imprime "3". Flip e flop de volta quando x==3
(1..10).each {|x| print x if x==3..x>=3 }
# Imprime "34". Flip quando x == 3 e flop quando x==4
(1..10).each {|x| print x if x==3...x>=3 } # Imprime "34"
Mapa mental
Exemplo prático
O próprio Matz desencoraja o uso de flip-flops (Matz, p. 110), porém podem ser úteis em alguns casos de leitura de arquivos e sources, como o exemplo a seguir (fonte):
code = <<-CODE
/**
* Some comments
* longer comments here that we can parse.
*
* Wahoo
*/
function subroutine() {
}
/* some more comments */
/**
* Another comment.
*/
function something() {
}
CODE
comments = code.collect { |line| line if (line =~ /^[\s]*\/\*/)..(line =~ /^[\s]*\*\//) }.join
puts comments
# Retorna
/**
* Some comments
* longer comments here that we can parse.
*
* Wahoo
*/
/* some more comments */
/**
* Another comment.
*/
Referências
- MATSUMOTO, Yukihiro; FLANAGAM, David. The Ruby Programming Language. 1st ed., p. 109-111, 2008.
- Ruby Flip Flop or Range Operators
- http://stackoverflow.com/questions/1111286/when-would-a-ruby-flip-flop-be-useful
Tags: 
Alfred Reinold Baudisch em Ruby, Ruby on Rails, Objective C e desenvolvimento de jogos para iPhone.


