¿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.
BEGIN y END también se usan para comentar, como:
=begin
This is a comment line
It can explain what the rest of the program is about
This was inspired from the perl style of programming
=end
Puede consultar el mismo aquí: https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)#Comments
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: