¿Qué significa << en Ruby?

81

Tengo codigo:

  def make_all_thumbs(source)
    sizes = ['1000','1100','1200','800','600']
    threads = []
    sizes.each do |s|
      threads << Thread.new(s) {
        create_thumbnail(source+'.png', source+'-'+s+'.png', s)
      }
    end
  end

que <<significa

Vyacheslav Loginov
fuente

Respuestas:

143

'<<' como método ordinario

En la mayoría de los casos, '<<' es un método definido como el resto de ellos, en su caso significa "agregar al final de esta matriz" (ver también aquí ).

Ese es en su caso particular, pero también hay muchas otras ocasiones en las que encontrará el método "<<". No lo llamaré 'operador' ya que en realidad es un método que se define en algún objeto que puede ser anulado por usted o implementado para sus propios objetos. Otros casos de '<<'

  • Concatenación de cadenas: "a" << "b"
  • Escritura de salida en un IO: io << "Una línea de texto \ n"
  • Escritura de datos en un resumen de mensajes, HMAC o cifrado: sha << "Texto para aplicar hash"
  • desplazamiento a la izquierda de un OpenSSL :: BN: bn << 2
  • ...

Definición de clase singleton

Luego está el misterioso cambio del alcance actual (= cambio de uno mismo) dentro del flujo del programa:

class A
  class << self
    puts self # self is the singleton class of A
  end
end

a = A.new
class << a
  puts self # now it's the singleton class of object a
end

El misterio class << selfme hizo preguntarme e investigar sobre las partes internas allí. Mientras que en todos los ejemplos que mencioné <<es realmente un método definido en una clase, es decir

obj << stuff

es equivalente a

obj.<<(stuff)

la class << selfconstrucción (o cualquier objeto en lugar del yo) es verdaderamente diferente. Es realmente una característica incorporada del lenguaje en sí, en CRuby se define en parse.y como

k_class tLSHFT expr

donde tLSHFT es un token '<<', k_class es la palabra clave 'class' y expr es una expresión arbitraria. Es decir, puedes escribir

class << <any expression>

y se 'desplazará' a la clase singleton del resultado de la expresión. La secuencia tLSHFT se analizará como una expresión 'NODE_SCLASS', que se denomina definición de clase Singleton (cf. node.c)

case NODE_SCLASS:
    ANN("singleton class definition");
    ANN("format: class << [nd_recv]; [nd_body]; end");
    ANN("example: class << obj; ..; end");
    F_NODE(nd_recv, "receiver");
    LAST_NODE;
    F_NODE(nd_body, "singleton class definition");
    break; 

Aquí Documentos

Y, cómo podría olvidarme de esos, Here Documents usa '<<' de una manera que nuevamente es totalmente diferente. Puede definir una cadena que abarque varias líneas de manera conveniente declarando

here_doc = <<_EOS_
The quick brown fox jumps over the lazy dog.
...
_EOS_

Para distinguir el 'operador aquí doc', un delimitador de cadena arbitrario debe seguir inmediatamente al '<<'. Todo lo que se encuentre entre ese delimitador inicial y la segunda aparición de ese mismo delimitador será parte de la cadena final. También es posible usar '<< -', la diferencia es que usar este último ignorará cualquier espacio en blanco inicial o final.

realzar
fuente
4
Respuesta muy completa. Puede confundir a los principiantes, pero como un sabio (podría haber) dicho, "haz una pregunta amplia, obtén una respuesta completa".
Kelvin
1
Hola, gracias @emboss: entonces << ¿es el equivalente a llamar al método push en una matriz?
BKSpurgeon
30

Se usa principalmente en matrices para agregar el valor al final de la matriz.

a = ["orange"]
a << "apple"
puts a

da esto

  ["naranja", "manzana"] 
resultado.

shajin
fuente
3
Un uso más de <<está en la herencia de clases
Zabba
7

Es el operador que le permite alimentar arreglos existentes , agregando nuevos elementos.

En el ejemplo anterior, solo está completando la matriz vacía threadscon 5 subprocesos nuevos.

Emiliano Poggi
fuente
6

'a << b' significa añadir b al final de a

Aditya Mukherji
fuente
6

En ruby ​​siempre tienes más una forma de hacer las cosas. Entonces, Ruby tiene algunos atajos agradables para nombres de métodos comunes. como este es para .push en lugar de escribir el nombre del método .push, simplemente puede usar <<, el operador de concatenación. de hecho, en algunos casos, puede utilizar cualquiera de estos para la misma operación .push y + con <<.

Como puede ver en este ejemplo:

alphabet = ["a", "b", "c"]
alphabet << "d" # Update me!
alphabet.push("e") # Update me!
print alphabet 
caption = "the boy is surrounded by "
caption << "weezards!" # Me, too!
caption += " and more. " # Me, too!
# .push can no be uses for concatenate 
print caption

entonces ves que el resultado es:

["a", "b", "c", "d", "e"]
the boy is surrounded by weezards! and more.

puede usar el operador << para insertar un elemento en una matriz o para concatenar una cadena a otra.

entonces, lo que está haciendo es crear un nuevo elemento / objeto Tipo de hilo y empujarlo a la matriz.

 threads << Thread.new(s) {
        create_thumbnail(source+'.png', source+'-'+s+'.png', s)
      }
Jesús González
fuente
5

En ruby, el operador '<<' se usa básicamente para:

  1. Agregar un valor en la matriz (en la última posición)

    [2, 4, 6] << 8 Dará [2, 4, 6, 8]

  2. También se utiliza para algunas operaciones de registro activo en ruby. Por ejemplo, tenemos un modelo Cart y LineItem asociado como carrito has_many line_items. Cart.find (A) .line_items devolverá el objeto ActiveRecord :: Associations con artículos de línea que pertenecen al carrito 'A'.

Ahora, para agregar (o decir asociar) otro elemento line_item (X) al carrito (A),

Cart.find(A).line_items << LineItem.find(X)
  1. Ahora para agregar otro LineItem al mismo carrito 'A', pero esta vez no crearemos ningún objeto line_item (quiero decir, no crearemos el objeto activerecord manualmente)

    Cart.find (A) .line_items << LineItem.new

En el código anterior << guardará el objeto y lo agregará a la matriz de asociación de registros activos del lado izquierdo.

Y muchos otros que ya están cubiertos en las respuestas anteriores.

shubham mishra
fuente
No todo el mundo conoce este comportamiento de <<. Gracias por mencionarlo.
Ammar Shah
0

Significa agregar al final (agregar).

a = [1,2,3]
a << 4
a = [1,2,3,4]
VeronikaS
fuente
0

Además, desde Ruby 2.6, el <<método se define también enProc .

Proc # << permite componer dos o más procs.

maicher
fuente