2011-08-17 19 views
9

Siempre he estado buscando algo así como Python's while/else struct en Ruby para mejorar mi código.Ruby equivalente para Python's for/else

Eso significa que el ciclo se ejecuta y si la condición en el ciclo no ha sido verdadera en cualquier momento, entonces devuelve el valor en la instrucción else.

En Ruby, no puedo hacer como esto:

if @items.empty? 
    "Empty" 
else 
    @items.each do |item| 
    item 
    end 
end 

Entonces, ¿hay una manera de mejorar esto?

Gracias de antemano.

Respuesta

3

Hm, se podría escribir como un ternario:

@items.empty? ? 'Empty' : @items.each { |item| item } 

Es posible que desee hacer algo más útil en su bloque sin embargo, ya each es ejecutado por sus efectos secundarios y devuelve el receptor originales.

actualización de acuerdo con su comentario: Creo que lo más cerca que podría conseguir es algo así como

unless @items.empty? 
    @items.each { |item| p item } 
else 
'Empty' 
end 
+0

No me gusta mucho en solo una línea. Eso no está más claro. Lo que quiero es algo así como while/else/end. Tal vez no sea posible, pero creo que la pregunta vale la pena. – Cydonia7

+1

Miré el 'while/else' de Python ahora, @Zabba tiene razón, el más cercano es probablemente un' unless..el' si no te gusta la forma ternaria. En mi humilde opinión, no tiene sentido tratar de traducir cada construcción de un idioma a otro, pero sí a YMMV. –

+0

No estaba tratando de traducir todo el lenguaje, pero creo que esta estructura en Python es realmente útil. Gracias por su respuesta :) – Cydonia7

24

Recuerde que el bloque iterador devuelve lo que puso en él, lo que puede ser probado para su uso posterior.

if arr.each do |item| 
    item.some_action(some_arg) 
end.empty? 
    else_condition_here 
end 
+3

Esto es horriblemente increíble. –

0

Una forma más o menos funcional:

empty_action = { true => proc{ "Empty"}, 
       false => proc{ |arr| arr.each { |item| item }} } 

empty_action[@items.empty?][@items] 
1

Ya que estamos en Rubí, vamos a divertirnos. Ruby tiene potente case construcción, que podría ser utilizado como este:

case items 
when -:empty? then "Empty" 
else items.each { |member| 
    # do something with each collection member 
    } 
end 

Pero para hacer que el código anterior, tenemos que modificar la clase nativa Symbol primero. La modificación de las clases nativas es la especialidad de Ruby. Esto debe hacerse solo una vez, generalmente en una biblioteca (gema), y lo ayuda para siempre. En este caso, la modificación será:

class Symbol 
    def [email protected] 
    Object.new 
    .define_singleton_method :=== do |o| o.send self end 
    end 
end 

Este código sobrecarga el (-) el operador del Symbol clase de tal manera menos unitario, que diciendo -:sym devuelve un mono nuevo objeto vacío parcheado con :=== método, que se utiliza detrás de escena por la declaración del caso.