ruby reserved-words

¿Para qué se usan las palabras reservadas BEGIN o END en Ruby?



reserved-words (6)

Esta es una palabra muy difícil de encontrar porque en la mayoría de los casos no son sensibles durante una búsqueda. Lo mejor que pude encontrar fuera de la documentación es una prueba en IRB.

BEGIN{puts x = 10} 10


BEGIN / END es realmente útil cuando se usa la opción -e para procesar un flujo. Por ejemplo, para sumar un archivo de números:

cat <<EOF > numbers 1 5 10 20 EOF cat numbers | ruby -ane ''BEGIN { $t=0}; END {puts $t}; $t += $_.to_i''

observe cómo BEGIN reduce a cero el global, y el FIN imprime el resultado.



Como todas las keywords BEGIN y END se documentan como métodos de instancia pública de Object (aunque no los verá devueltos desde Object.public_instance_methods )

BEGIN Designa, a través del bloque de código, el código que se ejecutará incondicionalmente antes de que comience la ejecución secuencial del programa. A veces se utiliza para simular referencias hacia adelante a métodos.

puts times_3(gets.to_i) BEGIN { def times_3(n) n * 3 end }

END Designa, a través del bloque de código, el código que se ejecutará justo antes de la finalización del programa.

END { puts "Bye!" }

Algunas explicaciones más detalladas de la Guía de programación de Ruby The Pragmatic Programmer

Bloques de inicio y fin

Cada archivo fuente de Ruby puede declarar que se ejecutan bloques de código mientras el archivo se está cargando (los bloques BEGIN) y después de que el programa haya terminado de ejecutarse (los bloques END).

BEGIN { begin code } END { end code }

Un programa puede incluir múltiples bloques BEGIN y END. Los bloques BEGIN se ejecutan en el orden en que se encuentran. Los bloques finales se ejecutan en orden inverso.


Del lenguaje de programación Ruby:

Bloques de BEGIN y fin

Cada archivo fuente de Ruby puede declarar que se ejecutan bloques de código mientras el archivo se está cargando (los bloques BEGIN ) y después de que el programa haya terminado de ejecutarse (los bloques END ).

BEGIN { # begin code } END { # end code }

Un programa puede incluir múltiples bloques BEGIN y END . BEGIN bloques BEGIN se ejecutan en el orden en que se encuentran. END bloques END se ejecutan en orden inverso.

Asi que:

$ cat beginend.rb END { puts :end } BEGIN { puts :begin } END { puts :end2 } BEGIN { puts :begin2 } puts :run $ ruby beginend.rb begin begin2 run end2 end


El bloque BEGIN es exactamente lo que puede suponer, y es que el bloque dado se ejecutará antes que el resto del código en su programa.

Este es un ejemplo.

puts "Goodbye cruel world!" BEGIN { puts "Hello World!" }

Espero que eso ayude.

Hay un ejemplo práctico de esto en un minitest en el que una colección de valores se coloca fuera del camino al final del archivo, pero se evalúa primero.


Una cosa que no se ha mencionado es que en versiones anteriores de Ruby, BEGIN era incondicional:

if false BEGIN { puts "Up is down, hot is cold, good is evil!" } end

Si lo intentas con Ruby 1.8.7, la oración se imprime, aunque esté en la rama de if no se toma.

Bajo Ruby 2.0.0, es un error de sintaxis usar BEGIN fuera del nivel superior (una forma mucho más inteligente de manejar eso):

unconditional.rb:2: BEGIN is permitted only at toplevel BEGIN { puts "Up is down, hot is cold, good is evil!" } ^

Edición : En cierto modo, nadie ha respondido la pregunta que plantea en su comentario: ¿Por qué Ruby ha BEGIN ? Lo intentaré. BEGIN llega a Ruby (como muchas otras cosas) de Perl . Perl lo tiene porque existió en awk . Tenía mucho sentido en awk porque, de forma predeterminada, un archivo awk consta de una serie de patrones y acciones:

/foo/ { print $1 } /bar/ { print $2 }

Cada patrón se comprueba para cada línea. Si el patrón coincide, entonces se realiza la acción. De lo contrario, awk pasa al siguiente patrón. Entonces, en el mini script anterior, si la línea coincide con ''foo'', se imprime el primer campo. Si la línea coincide con ''barra'', se imprime el segundo campo.

Pero ahora puede ver la brecha que los bloques de COMIENZO (y END ) llenan: Qué sucede si desea hacer algo incondicionalmente antes de que se haya probado cualquier entrada o después de que se haya visto toda la entrada (como imprimir un encabezado en la parte superior de su informe) o imprimir una fila de totales al final del informe)? Las líneas normales de awk de patrón + acción no pueden ayudarte allí.

Es por eso que BEGIN y END existen. Pero no estoy seguro de cuán útiles son para los scripts de Ruby modernos e idiomáticos. Pero como señala dbenhur en los comentarios, todavía puedes usar Ruby muy bien para los de una sola línea de awk . (También tengo un recuerdo de que MiniTest, la biblioteca de pruebas estándar de Ruby, solía usar una función at_exit para las pruebas, pero no estoy seguro de que así sea).

Dos buenos enlaces sobre Ruby, awk y Ruby de una sola línea: