Buscar..


Observaciones

Los operadores son métodos

La mayoría de los operadores son en realidad solo métodos, por lo que x + y está llamando al método + de x con el argumento y , que se escribiría x.+(y) . Si escribe un método propio que tenga un significado semántico de un operador determinado, puede implementar su variante en la clase.

Como un ejemplo tonto:

# A class that lets you operate on numbers by name.
class NamedInteger
  name_to_value = { 'one' => 1, 'two' => 2, ... }

  # define the plus method
  def + (left_addend, right_addend)
    name_to_value(left_addend) + name_to_value(right_addend)
  end

  ...
end

Cuándo usar && vs. and , || vs. or

Tenga en cuenta que hay dos formas de expresar valores booleanos, ya sea && o and , y || o or - a menudo son intercambiables, pero no siempre. Nos referiremos a ellos como variantes de "carácter" y "palabra".

Las variantes de caracteres tienen mayor prioridad, por lo que reducir la necesidad de paréntesis en declaraciones más complejas ayuda a evitar errores inesperados.

Las variantes de la palabra originalmente fueron pensadas como operadores de flujo de control en lugar de operadores booleanos. Es decir, fueron diseñados para ser utilizados en declaraciones de métodos encadenados:

raise 'an error' and return

Si bien pueden utilizarse como operadores booleanos, su menor prioridad los hace impredecibles.

En segundo lugar, muchos rubyists prefieren la variante de caracteres cuando crean una expresión booleana (una que se evalúa como true o false ) como x.nil? || x.empty? . Por otro lado, las variantes de la palabra se prefieren en los casos en que se evalúan una serie de métodos , y uno puede fallar. Por ejemplo, una expresión idiomática común que usa la variante de la palabra para los métodos que devuelven nil en caso de falla podría ser:

def deliver_email
  # If the first fails, try the backup, and if that works, all good
  deliver_by_primary or deliver_by_backup and return
  # error handling code
end

Precedencia y métodos del operador

De mayor a menor, esta es la tabla de precedencia para Ruby. Las operaciones de alta precedencia suceden antes de las operaciones de baja precedencia.

╔═══════════════════════╦════════════════════════════════════════╦═════════╗
║ Operators             ║                 Operations             ║ Method? ║
╠═══════════════════════╬════════════════════════════════════════╬═════════╣
║ .                     ║ Method call (e.g. foo.bar)             ║         ║
║ []  []=               ║ Bracket Lookup, Bracket Set            ║    ✓¹   ║
║ ! ~ +                 ║ Boolean NOT, complement, unary plus    ║    ✓²   ║
║ **                    ║ Exponentiation                         ║    ✓    ║
║ -                     ║ Unary minus                            ║    ✓²   ║
║ * / %                 ║ Multiplication, division, modulo       ║    ✓    ║
║ + -                   ║ Addition, subtraction                  ║    ✓    ║
║ << >>                 ║ Bitwise shift                          ║    ✓    ║
║ &                     ║ Bitwise AND                            ║    ✓    ║
║ | ^                   ║ Bitwise OR, Bitwise XOR                ║    ✓    ║
║ < <= >= >             ║ Comparison                             ║    ✓    ║
║ <=> == != === =~ !~   ║ Equality, pattern matching, comparison ║    ✓³   ║
║ &&                    ║ Boolean AND                            ║         ║
║ ||                    ║ Boolean OR                             ║         ║
║ .. ...                ║ Inclusive range, Exclusive range       ║         ║
║ ? :                   ║ Ternary operator                       ║         ║
║ rescue                ║ Modifier rescue                        ║         ║
║ = += -=               ║ Assignments                            ║         ║
║ defined?              ║ Defined operator                       ║         ║
║ not                   ║ Boolean NOT                            ║         ║
║ or and                ║ Boolean OR, Boolean AND                ║         ║
║ if unless while until ║ Modifier if, unless, while, until      ║         ║
║ { }                   ║ Block with braces                      ║         ║
║ do end                ║ Block with do end                      ║         ║
╚═══════════════════════╩════════════════════════════════════════╩═════════╝

Unary + y unary - son para +obj , -obj o -(some_expression) .

Modificador-si, modificador-a menos, etc. son para las versiones modificadoras de esas palabras clave. Por ejemplo, esta es una expresión de modificador, a menos que:

a += 1 unless a.zero?

Los operadores con ✓ pueden definirse como métodos. La mayoría de los métodos se nombran exactamente como se nombra al operador, por ejemplo:

class Foo
  def **(x)
    puts "Raising to the power of #{x}"
  end
  def <<(y)
    puts "Shifting left by #{y}"
  end
  def !
    puts "Boolean negation"
  end
end

Foo.new ** 2     #=> "Raising to the power of 2"
Foo.new << 3     #=> "Shifting left by 3"
!Foo.new         #=> "Boolean negation"

¹ Los métodos de Búsqueda de corchetes y Conjunto de corchetes ( [] y []= ) tienen sus argumentos definidos después del nombre, por ejemplo:

class Foo
  def [](x)
    puts "Looking up item #{x}"
  end
  def []=(x,y)
    puts "Setting item #{x} to #{y}"
  end
end

f = Foo.new
f[:cats] = 42    #=> "Setting item cats to 42"
f[17]            #=> "Looking up item 17"

² Los operadores "unary plus" y "unary minus" se definen como métodos denominados +@ y -@ , por ejemplo

class Foo
  def -@
    puts "unary minus"
  end
  def +@
    puts "unary plus"
  end
end

f = Foo.new
+f               #=> "unary plus"
-f               #=> "unary minus"

³ En las primeras versiones de Ruby, el operador de desigualdad != Y el operador no coincidente !~ No se podían definir como métodos. En su lugar, se invocó el método para el operador de igualdad correspondiente == o el operador coincidente =~ , y el resultado de ese método fue booleano invertido por Ruby.

Si no define sus propios operadores != O !~ , El comportamiento anterior sigue siendo cierto. Sin embargo, a partir de Ruby 1.9.1, esos dos operadores también pueden definirse como métodos:

class Foo
  def ==(x)
    puts "checking for EQUALITY with #{x}, returning false"
    false
  end
end

f = Foo.new
x = (f == 42)    #=> "checking for EQUALITY with 42, returning false"
puts x           #=> "false"
x = (f != 42)    #=> "checking for EQUALITY with 42, returning false"
puts x           #=> "true"

class Foo
  def !=(x)
    puts "Checking for INequality with #{x}"
  end
end

f != 42          #=> "checking for INequality with 42"

Operador de igualdad de casos (===)

También conocido como triple igual .

Este operador no prueba la igualdad, sino que prueba si el operando derecho tiene una relación IS A con el operando izquierdo. Como tal, el nombre popular operador de igualdad de casos es engañoso.

Esta respuesta SO lo describe así: la mejor manera de describir a === b es "si tengo un cajón con la etiqueta a , ¿tiene sentido poner b en él?" En otras palabras, ¿el conjunto a incluye al miembro b ?

Ejemplos ( fuente )

(1..5) === 3            # => true
(1..5) === 6            # => false

Integer === 42          # => true
Integer === 'fourtytwo' # => false

/ell/ === 'Hello'       # => true
/ell/ === 'Foobar'      # => false

Clases que anulan ===

Muchas clases anulan === para proporcionar semántica significativa en las declaraciones de casos. Algunos de ellos son:

╔═════════════════╦════════════════════╗
║      Class      ║     Synonym for    ║
╠═════════════════╬════════════════════╣
║ Array           ║ ==                 ║
║                 ║                    ║
║ Date            ║ ==                 ║
║                 ║                    ║
║ Module          ║ is_a?              ║
║                 ║                    ║
║ Object          ║ ==                 ║
║                 ║                    ║
║ Range           ║ include?           ║
║                 ║                    ║
║ Regexp          ║ =~                 ║
║                 ║                    ║
║ String          ║ ==                 ║
╚═════════════════╩════════════════════╝

Práctica recomendada

Se debe evitar el uso explícito del operador de igualdad de casos === . No prueba la igualdad sino la subsunción , y su uso puede ser confuso. El código es más claro y más fácil de entender cuando se utiliza el método de sinónimos en su lugar.

# Bad
Integer === 42
(1..5) === 3
/ell/ === 'Hello'

# Good, uses synonym method
42.is_a?(Integer)
(1..5).include?(3)
/ell/ =~ 'Hello'

Operador de navegación segura

Ruby 2.3.0 agregó el operador de navegación segura , &. . Este operador está destinado a acortar el paradigma de object && object.property && object.property.method en sentencias condicionales.

Por ejemplo, tiene un objeto House con una propiedad de address y desea buscar el street_name la street_name en la address . Para programar esto de manera segura para evitar errores nulos en versiones anteriores de Ruby, usarías un código como este:

if house && house.address && house.address.street_name
  house.address.street_name
end

El operador de navegación segura acorta esta condición. En su lugar, puede escribir:

if house&.address&.street_name
  house.address.street_name
end

Precaución:
El operador de navegación segura no tiene exactamente el mismo comportamiento que el condicional encadenado. Usando el condicional encadenado (primer ejemplo), el bloque if no se ejecutaría si, por ejemplo, la address fuera false . El operador de navegación segura solo reconoce valores nil , pero permite valores como false . Si la address es false , el uso del SNO producirá un error:

house&.address&.street_name
# => undefined method `address' for false:FalseClass


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