2009-03-20 13 views
56

¿Para qué sirven los símbolos de tubería en Ruby?¿Para qué son esos símbolos de tubería en Ruby?

estoy aprendiendo Ruby y RoR, viniendo de un fondo PHP y Java, pero sigo viniendo a través de código como este:

def new 
    @post = Post.new 

    respond_to do |format| 
    format.html # new.html.erb 
    format.xml { render :xml => @post } 
    end 
end 

¿Cuál es la parte |format| hacer? ¿Cuál es la sintaxis equivalente de estos símbolos de tubería en PHP/Java?

Respuesta

42

Son las variables cedidas al bloque.

def this_method_takes_a_block 
    yield(5) 
end 

this_method_takes_a_block do |num| 
    puts num 
end 

Qué salidas "5". Un ejemplo más arcano:

def this_silly_method_too(num) 
    yield(num + 5) 
end 

this_silly_method_too(3) do |wtf| 
    puts wtf + 1 
end 

La salida es "9".

+0

¿dónde va 'wtf' cuando termina el bloque' | wtf | '? – ThorSummoner

+0

Tiene un alcance al bloque, por lo que no está disponible fuera de él. En otras palabras: se va. –

+0

Si es mutable? Tiene que ser así, de lo contrario no tengo ni idea de cómo Vagrantfile puede usarlos como método de configuración. – ThorSummoner

5

El código del do al end define un Ruby block. La palabra format es un parámetro del bloque. El bloque se pasa junto con la llamada al método, y el método llamado puede yield valores para el bloque.

Consulte cualquier texto en Ruby para obtener más detalles, esta es una característica central de Ruby que verá todo el tiempo.

+1

No, el código entre do y end es un ruby ​​block. Los términos entre las barras verticales son parámetros de ese bloque. – rampion

+0

IIRC, la sintaxis de la tubería es tomada de Smalltalk. –

+0

Sí, excepto que Smalltalk acaba de usar una tubería. – Chuck

3

El equivalente en Java sería algo así como

// Prior definitions 

interface RespondToHandler 
{ 
    public void doFormatting(FormatThingummy format); 
} 

void respondTo(RespondToHandler) 
{ 
    // ... 
} 

// Equivalent of your quoted code 

respondTo(new RespondToHandler(){ 
    public void doFormatting(FormatThingummy format) 
    { 
     format.html(); 
     format.xml(); 
    } 
}); 
+0

Brent, si quiere decir con eso, que la versión de Java es prolija y prolija, sí, estoy de acuerdo con usted. Pero, de nuevo, esta es una construcción menos idiomática en Java. Ruby lo usa todo el tiempo, Java lo es menos. –

+0

el formato.html(); format.xml(); parte probablemente sería más como una declaración de cambio, ya que estaría cambiando el formato que se solicitó. – jonnii

+0

Un ejemplo más limpio es la construcción equivalente en JavaScript: responder_a (nueva función (formato) {formato.html(); formato.xml();}); Encuentro la falta de soporte de functor verdadero de Java realmente molesto; no son difíciles de usar en absoluto, a menos que los hayas aprendido con clases anónimas en Java. –

2

Parámetros de una sentada manzana entre las | símbolos.

5
@names.each do |name| 
    puts "Hello #{name}!" 
end 

en http://www.ruby-lang.org/en/documentation/quickstart/4/ se acompaña de esta explicación:

each es un método que acepta un bloque de código a continuación, ejecuta ese bloque de código para cada elemento en una lista, y el bit entre do y end es solo un bloque. Un bloque es como una función anónima o lambda. La variable entre caracteres de tubería es el parámetro para este bloque.

Lo que sucede aquí es que para cada entrada en una lista, name está vinculado a ese elemento de lista, y luego la expresión puts "Hello #{name}!" se ejecuta con ese nombre.

24

Esto también me resultaba muy extraño al principio, pero espero que esta explicación/tutorial te ayude.

La documentación touches the subject, de una manera bastante buena - si mi respuesta no ayuda, estoy seguro de que su guía lo hará.

Primero, encienda el intérprete de Ruby Interactivo escribiendo irb en su shell y presionando Ingrese.

Tipo algo como:

the_numbers = ['ett','tva','tre','fyra','fem'] # congratulations! You now know how to count to five in Swedish. 

apenas de modo que tenemos una matriz para jugar.Luego creamos el ciclo:

the_numbers.each do |linustorvalds| 
    puts linustorvalds 
end 

Saldrá todos los números, separados por líneas nuevas.

En otros idiomas que tendría que escribir algo como:

for (i = 0; i < the_numbers.length; i++) { 
    linustorvalds = the_numbers[i] 
    print linustorvalds; 
} 

Las cosas importantes a tener en cuenta son que el |thing_inside_the_pipes| puede ser cualquier cosa, siempre y cuando se está utilizando de forma coherente. Y entiendo que estamos hablando de bucles, eso fue algo que no obtuve hasta más adelante.

+2

En algunos "otros idiomas" (Python), escribe 'para linustorvalds en los números que imprimen linustorvalds'. Un poco más intuitivo, tal vez. –

+1

Absolutamente correcto. Seleccioné la sintaxis del estilo C porque sospecho que más personas que vienen a ruby ​​están familiarizadas con eso, pero espero que también lean tu comentario. –

+0

Gracias. La sección "otros idiomas" me ayudó a entender lo que estaba pasando. +1. – rayryeng

1

para hacerla más clara aún más, si es necesario:

las barras de tubo esencialmente hacen una nueva variable para mantener el valor generado a partir de la llamada al método anterior. Algo parecido a:

definición original de su método:

def example_method_a(argumentPassedIn) 
    yield(argumentPassedIn + 200) 
end 

Cómo se consume:

example_method_a(100) do |newVariable| 
    puts newVariable; 
end 

Es casi lo mismo que escribir esto:

newVariable = example_method_a(100) 
puts newVariable 

wher e, newVariable = 200 + 100 = 300: D!

Cuestiones relacionadas