Buscar..


si, elsif, else y end

Ruby ofrece las expresiones if y else esperadas para la lógica de bifurcación, terminadas por la palabra clave end :

# Simulate flipping a coin
result = [:heads, :tails].sample

if result == :heads
  puts 'The coin-toss came up "heads"'
else
  puts 'The coin-toss came up "tails"'
end

En Ruby, if las declaraciones son expresiones que se evalúan como un valor, y el resultado se puede asignar a una variable:

status = if age < 18
           :minor
         else
           :adult
         end

Ruby también ofrece operadores ternarios de estilo C ( consulte aquí para obtener detalles ) que se pueden expresar como:

some_statement ? if_true : if_false  

Esto significa que el ejemplo anterior usando if-else también puede escribirse como

status = age < 18 ? :minor : :adult

Además, Ruby ofrece la palabra clave elsif que acepta una expresión para habilitar lógica de bifurcación adicional:

label = if shirt_size == :s
          'small'
        elsif shirt_size == :m
          'medium'
        elsif shirt_size == :l
          'large'
        else
          'unknown size'
        end

Si ninguna de las condiciones en una cadena if / elsif es verdadera, y no hay else cláusula, entonces la expresión se evalúa como nula. Esto puede ser útil dentro de la interpolación de cadenas, ya que nil.to_s es la cadena vacía:

"user#{'s' if @users.size != 1}"

Valores de verdad y falsedad.

En Ruby, hay exactamente dos valores que se consideran "falsos" y devolverán falso cuando se analicen como una condición para una expresión if . Son:

  • nil
  • booleano false

Todos los demás valores se consideran "veraces", incluidos:

  • 0 - cero numérico (entero o no)
  • "" - Cuerdas vacías
  • "\n" - Cadenas que contienen solo espacios en blanco
  • [] - Arreglos vacíos
  • {} - Hashes vacíos

Tomemos, por ejemplo, el siguiente código:

def check_truthy(var_name, var)
  is_truthy = var ? "truthy" : "falsy"
  puts "#{var_name} is #{is_truthy}"
end

check_truthy("false", false)
check_truthy("nil", nil)
check_truthy("0", 0)
check_truthy("empty string", "")
check_truthy("\\n", "\n")
check_truthy("empty array", [])
check_truthy("empty hash", {})

Saldrá:

false is falsy
nil is falsy
0 is truthy
empty string is truthy
\n is truthy
empty array is truthy
empty hash is truthy

mientras, hasta

A while bucle se ejecuta el bloque, mientras que se cumple la condición dada:

i = 0
while i < 5
  puts "Iteration ##{i}"
  i +=1
end

Un bucle until ejecuta el bloque mientras que el condicional es falso:

i = 0
until i == 5
  puts "Iteration ##{i}"
  i +=1
end

En línea si / a menos

Un patrón común es usar una línea o cola, if o a unless :

puts "x is less than 5" if x < 5

Esto se conoce como un modificador condicional y es una forma útil de agregar código de guarda simple y devoluciones tempranas:

def save_to_file(data, filename)
  raise "no filename given" if filename.empty?
  return false unless data.valid?

  File.write(filename, data)
end

No es posible agregar una cláusula else a estos modificadores. Además, generalmente no se recomienda usar modificadores condicionales dentro de la lógica principal. Para código complejo, uno debería usar normal if , elsif , else lugar.

a no ser que

Una declaración común es if !(some condition) . Ruby ofrece la alternativa de la declaración unless .

La estructura es exactamente la misma que una instrucción if , excepto que la condición es negativa. Además, la declaración unless no es compatible con elsif , pero sí es compatible con else :

# Prints not inclusive
unless 'hellow'.include?('all')
  puts 'not inclusive'
end

Declaración del caso

Ruby usa la palabra clave del case para las declaraciones de cambio.

Según los documentos de Ruby :

Las declaraciones de casos consisten en una condición opcional, que está en la posición de un argumento a case , y cero o más when cláusulas. La primera cláusula when para que coincida con la condición (o para evaluar la verdad booleana, si la condición es nula) "gana" y se ejecuta su stanza de código. El valor de la declaración de caso es el valor de la cláusula when éxito, o nil si no existe tal cláusula.

Una declaración de caso puede terminar con una cláusula else . Cada una when una declaración puede tener múltiples valores candidatos, separados por comas.

Ejemplo:

case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
else
  puts "Some other number"
end

Versión más corta:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end

El valor del case cláusula se empareja con cada when cláusula usando el === método (no == ). Por lo tanto, se puede utilizar con una variedad de diferentes tipos de objetos.

Una declaración de case se puede utilizar con rangos :

case 17
when 13..19
  puts "teenager"
end

Se puede usar una declaración de case con un Regexp :

case "google"
when /oo/
  puts "word contains oo"
end

Se puede usar una declaración de case con un Proc o lambda:

case 44
when -> (n) { n.even? or n < 0 }
  puts "even or less than zero"
end

Se puede usar una declaración de case con las Clases :

case x
when Integer
  puts "It's an integer"
when String
  puts "It's a string"
end

Al implementar el método === puede crear sus propias clases de coincidencia:

class Empty
  def self.===(object)
    !object or "" == object
  end
end

case ""
when Empty
  puts "name was empty"
else
  puts "name is not empty"
end

Se puede usar una declaración de case sin que coincida un valor con:

case
when ENV['A'] == 'Y'
  puts 'A'
when ENV['B'] == 'Y'
  puts 'B'
else
  puts 'Neither A nor B'
end

Una declaración de case tiene un valor, por lo que puede usarla como un argumento de método o en una asignación:

description = case 16
              when 13..19 then "teenager"
              else ""
              end

Control de bucle con ruptura, siguiente y rehacer

El flujo de ejecución de un bloque de Ruby se puede controlar con las declaraciones break , next y redo .

break

La sentencia break saldrá del bloque inmediatamente. Cualquier instrucción restante en el bloque se omitirá, y la iteración terminará:

actions = %w(run jump swim exit macarena)
index = 0

while index < actions.length
  action = actions[index]

  break if action == "exit"

  index += 1
  puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim

next

La next declaración volverá a la parte superior del bloque inmediatamente y continuará con la siguiente iteración. Cualquier instrucción restante en el bloque será omitida:

actions = %w(run jump swim rest macarena)
index = 0

while index < actions.length
  action = actions[index]
  index += 1

  next if action == "rest"

  puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: macarena

redo

La instrucción de redo volverá a la parte superior del bloque inmediatamente y volverá a intentar la misma iteración. Cualquier instrucción restante en el bloque será omitida:

actions = %w(run jump swim sleep macarena)
index = 0
repeat_count = 0

while index < actions.length
  action = actions[index]
  puts "Currently doing this action: #{action}"

  if action == "sleep"
    repeat_count += 1
    redo if repeat_count < 3
  end

  index += 1
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: macarena

Enumerable enumerable

Además de los bucles, estas declaraciones funcionan con los métodos de iteración Enumerable, como each y el map :

[1, 2, 3].each do |item|
  next if item.even?
  puts "Item: #{item}"
end

# Item: 1
# Item: 3

Valores de bloque de resultados

Tanto en la declaración de break como en la next , se puede proporcionar un valor, y se usará como un valor de resultado de bloque:

even_value = for value in [1, 2, 3]
  break value if value.even?
end

puts "The first even value is: #{even_value}"

# The first even value is: 2

lanzar

A diferencia de muchos otros lenguajes de programación, las palabras clave de throw y catch no están relacionadas con el manejo de excepciones en Ruby.

En Ruby, throw y catch actúan un poco como etiquetas en otros idiomas. Se utilizan para cambiar el flujo de control, pero no están relacionados con un concepto de "error", como lo son las excepciones.

catch(:out) do
  catch(:nested) do
    puts "nested"
  end

  puts "before"
  throw :out
  puts "will not be executed"
end
puts "after"
# prints "nested", "before", "after"

Flujo de control con sentencias lógicas.

Si bien puede parecer contrario a la intuición, puede usar operadores lógicos para determinar si se ejecuta una declaración. Por ejemplo:

File.exist?(filename) or STDERR.puts "#{filename} does not exist!"

Esto verificará si el archivo existe y solo imprimirá el mensaje de error si no existe. La declaración or es perezosa, lo que significa que dejará de ejecutarse una vez que esté seguro de si el valor es verdadero o falso. Tan pronto como se determina que el primer término es verdadero, no hay necesidad de verificar el valor del otro término. Pero si el primer término es falso, debe verificar el segundo término.

Un uso común es establecer un valor predeterminado:

glass = glass or 'full' # Optimist! 

Eso establece el valor del glass en 'lleno' si aún no está configurado. Más concisamente, puede utilizar la versión simbólica de or :

glass ||= 'empty' # Pessimist. 

También es posible ejecutar la segunda instrucción solo si la primera es falsa:

File.exist?(filename) and puts "#{filename} found!"

De nuevo, and es perezoso, por lo que solo ejecutará la segunda instrucción si es necesario para llegar a un valor.

El operador or tiene menor prioridad que and . Del mismo modo, || tiene menor precedencia que && . Las formas de los símbolos tienen mayor prioridad que las formas de las palabras. Esto es útil para saber cuándo desea mezclar esta técnica con la asignación:

a = 1 and b = 2
#=> a==1
#=> b==2
a = 1 && b = 2; puts a, b
#=> a==2
#=> b==2

Tenga en cuenta que la Guía de estilo Ruby recomienda :

El and y or palabras clave están prohibidos. La legibilidad añadida mínima no vale la pena por la alta probabilidad de introducir errores sutiles. Para expresiones booleanas, use siempre && y || en lugar. Para control de flujo, use if y a unless ; && y || También son aceptables pero menos claras.

comenzar

El bloque de begin es una estructura de control que agrupa varias declaraciones.

begin
  a = 7
  b = 6
  a * b
end

Un bloque de begin devolverá el valor de la última instrucción en el bloque. El siguiente ejemplo devolverá 3 .

begin
  1
  2
  3
end

El bloque de begin es útil para la asignación condicional utilizando el operador ||= donde se pueden requerir varias declaraciones para devolver un resultado.

circumference ||=
  begin
    radius = 7
    tau = Math::PI * 2
    tau * radius
  end

También se puede combinar con otras estructuras de bloque, como rescue , ensure , while if , a unless , etc. para proporcionar un mayor control del flujo del programa.

Begin bloques Begin no son bloques de código, como { ... } o do ... end ; no pueden ser pasados ​​a funciones.

retorno vs. siguiente: retorno no local en un bloque

Considere este fragmento roto :

def foo
  bar = [1, 2, 3, 4].map do |x|
    return 0 if x.even?
    x
  end
  puts 'baz'
  bar
end
foo # => 0

Se podría esperar que el return produzca un valor para la matriz de resultados de bloque del map . Entonces, el valor de retorno de foo sería [1, 0, 3, 0] . En su lugar, return devuelve un valor del método foo . Tenga en cuenta que baz no se imprime, lo que significa que la ejecución nunca llegó a esa línea.

next con un valor hace el truco. Actúa como un return nivel de bloque.

def foo
  bar = [1, 2, 3, 4].map do |x|
    next 0 if x.even?
    x
  end
  puts 'baz'
  bar
end
foo # baz
    # => [1, 0, 3, 0]

En ausencia de una return , el valor devuelto por el bloque es el valor de su última expresión.

Or-Equals / Operador de asignación condicional (|| =)

Ruby tiene un operador o-igual que permite que un valor se asigne a una variable si y solo si esa variable se evalúa como nil o false .

 ||= # this is the operator that achieves this. 

este operador con los tubos dobles que representan o y el signo igual que representa la asignación de un valor. Puedes pensar que representa algo como esto:

 x = x || y

Este ejemplo anterior no es correcto. El operador or-equals en realidad representa esto:

 x || x = y

Si x evalúa como nil o false , a x se le asigna el valor de y , de lo contrario, no se modifica.

Aquí hay un caso práctico de uso del operador or-igual. Imagina que tienes una parte de tu código que se espera que envíe un correo electrónico a un usuario. ¿Qué debe hacer si por cualquier motivo no hay un correo electrónico para este usuario? Podrías escribir algo como esto:

 if user_email.nil?
    user_email = "[email protected]"
 end

Usando el operador or-equals podemos cortar todo este fragmento de código, brindando un control y funcionalidad claros y claros.

 user_email ||= "[email protected]"

En los casos donde false es un valor válido, se debe tener cuidado de no anularlo accidentalmente:

has_been_run = false
has_been_run ||= true
#=> true

has_been_run = false
has_been_run = true if has_been_run.nil?
#=> false

Operador ternario

Ruby tiene un operador ternario ( ?: :), Que devuelve uno de los dos valores en función de si una condición se evalúa como verdadera:

conditional ? value_if_truthy : value_if_falsy

value = true
value ? "true" : "false"
#=> "true"

value = false
value ? "true" : "false"
#=> "false"

es lo mismo que escribir if a then b else c end , aunque se prefiere el ternario

Ejemplos:

puts (if 1 then 2 else 3 end) # => 2

puts 1 ? 2 : 3                # => 2

x = if 1 then 2 else 3 end
puts x                        # => 2

Operador de flip-flop

El operador flip flop .. se usa entre dos condiciones en una declaración condicional:

(1..5).select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 3, 4]

La condición se evalúa como false hasta que la primera parte se vuelva true . Luego se evalúa como true hasta que la segunda parte se vuelva true . Después de eso cambia a false otra vez.

Este ejemplo ilustra lo que se está seleccionando:

[1, 2, 2, 3, 4, 4, 5].select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 2, 3, 4]

El operador de flip-flop solo trabaja dentro de ifs (incluyendo a unless ) y el operador ternario. De lo contrario, se está considerando como el operador de rango.

(1..5).select do |e|
  (e == 2) .. (e == 4)
end
# => ArgumentError: bad value for range

Puede cambiar de false a true y hacia atrás varias veces:

((1..5).to_a * 2).select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 3, 4, 2, 3, 4] 


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow