2010-02-10 20 views
13

que estaba buscando a través de un código fuente de Rails y se encontró con¿Qué significa array * string en Ruby?

# File vendor/rails/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb, line 129 
129:  def target! 
130:  @target * '' 
131:  end 

¿Qué hace la * '' hacer? ¿Es esa multiplicación por una cadena vacía ...? ¿Y por qué harías eso?

Respuesta

13

Esta es una sintaxis extraña. Estos son equivalentes:

>> [1, 2, 3] * 'joiner' 
=> "1joiner2joiner3" 

>> [1, 2, 3].join 'joiner' 
=> "1joiner2joiner3" 

por lo que en este caso se une a todas las entradas de @target en una sola cadena, sin nada entre las entradas.

Nota: si hace algo como [1, 2, 3] * 3 (utilizando int en lugar de str), obtendrá tres copias concatenadas de la matriz en su lugar.

+0

¿Eh ?! No hay nada "extraño" en la sintaxis del operador infijo (a menos que seas un fanático de Lisp o Forth). Prácticamente * cada * lenguaje de programación en el planeta tiene un operador infijo '*'. –

+5

@ Jörg: No es la parte de infijo lo que es extraño, es el hecho de que se está multiplicando una matriz por una cadena ...? –

+0

Estoy de acuerdo en que la semántica es confusa y, de hecho, extraña, pero lo que tanto Peter como Crudson se quejan no es la semántica, es la * sintaxis *, y estoy algo perplejo por eso. –

5

Se hace lo mismo que: la sugerencia de

["foo","bar","baz"].join 

http://ruby-doc.org/core/classes/Array.html#M002210

por Z.E.D., se utilizaría si quiere confundir a la gente y hacer que el código sea más propensa su error.

+2

Probablemente diría eso de manera diferente. Resulta en lo mismo que un [] .join, pero usar el método join() es más obvio y se usa más comúnmente. He visto varias recomendaciones de que no usamos el operador '*' con arreglos porque poca gente lo usa y es confuso. Compara la salida de [1,2] * ',' con [1,2] * 2 para ver un ejemplo de por qué no funciona bien con nuestros cerebros. –

+0

¿Estás argumentando que no hace lo mismo? El RDoc dice "equivalente a". La legibilidad es ortogonal a la implementación. – klochner

3

código realmente críptico de hecho.

Después de comprobar el código fuente, me di cuenta de que @target es realmente una instancia Array, sé que puede hacer cosas como esta

[5] * 5 # => [5,5,5,5,5] 

No sé donde se define Array#* (tal vez en ActiveSupport), pero lo que puedo decir es que, este es el comportamiento cuando se multiplica por un String

[1,2,3] * 'comma' # => "1comma2comma3" 
[1,2,3] * '' # => '123' 

Así que puedo inferir que se concatanating todos los elementos de la matriz sin cualquier separador

1

Dos observaciones:

  1. Tener una! terminar un nombre de método implica que se trata de una operación de mutación, que este ejemplo no parece ser.

  2. Como han dicho otros, es críptico. Yo iría por @ o @ target.to_s target.join

+1

Además, este tipo de código de rubí me pone triste porque el rubí es fácil de leer e idiomáticamente hermoso, y una sintaxis como esta me da recuerdos de Perl. – user253455

+0

Usted es la segunda persona en esta pregunta que se queja acerca de la sintaxis del operador infijo. No lo entiendo del todo Con la excepción de Lisp y Forth, casi todos los * lenguajes de programación * en el planeta tienen un operador infijo '*'. No hay nada "extraño" o "triste" sobre los operadores de infijo. –

+0

Por supuesto, pero este ejemplo hace que uno tenga que pensar brevemente para obtener la línea de código. Crear una cadena vacía para concatenar una matriz es un uso poco claro de *. No tengo absolutamente nada en contra del operador. – user253455

2

Array#* con un argumento String es equivalente a Array#join.

0

La única razón por la que veo que alguien quiere usar * para unir una matriz de cadenas es si quieren evitar la palabra join, que también se usa en los hilos.

Con el siguiente:

strings = ["John", "Smith"] 
threads = [Thread.new{puts "hai"}, Thread.new{ puts "world!"}] 
strings.join(" ") # Legit 
threads.each {|thread| thread.join} # Legit 

que podría cometer el error de hacer

threads.join # Not legit, but won't raise an error 

Si se ha sustituido con strings.joinstrings.*, entonces tendría un menor número de join s en el código. Ahora podría hacer un grep para ellos, y verificar que cada uno se está haciendo a un hilo, no a un conjunto. De hecho, puede elegir hacer Array#join lanzar una excepción.