2009-11-04 7 views
14

Sé lo que hacen todos, pero nunca me he encontrado en una situación en la que los haya necesitado. He usado BEGIN bloques en muchas ocasiones y END s de vez en cuando. BEGIN es especialmente útil cuando necesita modificar el entorno antes de que se ejecute el código, y he usado END en ciertas situaciones de depuración para atrapar información de estado importante para errores fatales difíciles de rastrear.¿Cuál es la utilidad de los bloques CHECK, UNITCHECK e INIT en Perl?

¿Alguna vez ha usado CHECK, UNITCHECK o INIT? Si es así, ¿para qué? ¿Y un bloque BEGIN no hubiera sido suficiente por alguna razón?

La documentación para los bloques está en PerlDoc.

Respuesta

5

Tenía un paquete de import función que haría un poco de procesamiento de trabajo pesado y luego hacer una llamada eval. ¿Cómo depurar algo así? La función de importación se ejecuta cuando el módulo use se lleva a cabo en tiempo de compilación (como si estuviera dentro de un bloque BEGIN). Por alguna razón (creo que fue porque necesitaba pasar parámetros a import con notación heredoc, pero podría haber sido otra cosa), no fue suficiente para decir require Module; Module->import(@args).

Así que mi solución fue construir la cadena para eval en import, y guardarla en otra variable. Luego ejecuté el eval en un bloque INIT. Cuando ejecutó el depurador, el primer punto de ejecución fue al comienzo del bloque INIT y pude usar el depurador para pasar la instrucción eval.

+0

Ahora recuerdo por qué no quería hacer 'require Module; Module-> import (@stuff)'. Fue porque ya tenía un conjunto de scripts de prueba que quería poder depurar, y no quería editar la declaración 'use Module' en cada archivo. – mob

+9

No necesita pasar por esas contorsiones para depurar el código de tiempo de compilación. Simplemente coloque $ DB :: single = 1 en cualquier lugar de su fuente y el depurador se detendrá en ese punto, sin importar en qué fase del procesamiento esté el programa. (Vea http://perldoc.perl.org/perldebug.html#Debugging -compile-time-statements) –

+0

Gracias Brian! Es bueno saberlo. – mob

7

Un uso interesante de los bloques CHECK se encuentra en "Programación avanzada de Perl" por Simon Cozens (O'Reilly) en el Capítulo 1, en la sección "Hacer las cosas más adelante con CHECK". Muestra cómo implementar el atributo "final" tipo java

Además, Devel :: Sub :: Trace usa bloques INIT para incert traces (esta información es de POD para Devel :: Hook que es un módulo usado para trabajar con los bloques con nombre)

+0

Además, nunca lo intenté, pero estos * podrían * aprovecharse de manera convincente para algunos enfoques burlones interesantes: si alguien tiene una idea, no dude en ampliar esta posibilidad como una respuesta separada. – DVK

3

Bueno, BEGIN bloques se ejecutan en tiempo de compilación, como usted sabe. Así que lo guardo en el código que necesita ejecutarse para que se importe mi módulo.

Escribí un script wrapper, para hacer todo lo que se estaba haciendo en un código repetitivo que ocurría en un par de cientos de scripts.

  • Hubo cosas que tuve que hacer para que la lectura del módulo fuera use -d. Que corrí en BEGIN bloques y import sub.
  • Pero también había todo lo repetitivo que inicializó los servicios que usaría la secuencia de comandos. Por lo tanto, ejecuté estas acciones en los bloques INIT.
  • Y ejecutó el código de limpieza y salida necesario en los bloques END.

Creo que CHECK tiene sentido si escribe módulos con motores XS, pero solo lo he usado un par de veces. Una vez creo que fue para ver las sugerencias en Intermedio Perl. Y no puedo recordar las otras razones.

Pero uso INIT bloques cuando siento que el código es más parte de la secuencia de comandos, que la configuración del módulo. En esencia, solo hago lo que es necesario durante el tiempo de compilación.

+0

Axeman: para la inicialización, ¿podría aclarar cuáles eran sus usos cuando el bloque INIT proporcionaba algo especial que no se podía conseguir simplemente colocando el código de inicio al inicio del programa regular? ¿Es solo para visualización/facilidad de mantenimiento? – DVK

+1

@DVK: He utilizado bloques INIT en módulos para realizar la inicialización de clase; el usuario no debería tener que saber sobre ese tipo de cosas. Desafortunadamente, PAR :: Packer tiene problemas con los bloques programados (INIT y CHECK en particular) por lo que esto no funciona para los módulos que pueden distribuirse de esa manera. Normalmente termino arrancando el bloque INIT a favor de un subinicializador 'initialize()' que se llama la primera vez que se invoca el constructor. –

+0

Los bloques CHECK no tienen nada que ver con los módulos XS. – rurban

1

perlmod explica esos bloques especiales, pero de hecho sólo se BEGIN y END se utilizan comúnmente. Son solo matrices de CV, LIFO o FIFO. Esos bloques permiten sincronizaciones separadas cuando se ejecuta código, independientemente de la ubicación en el archivo de origen. De modo que puede mantener las secciones de código juntas, pero se ejecutan en momentos diferentes (PHASES).

COMPROBACIÓN se añadió inicialmente para ejecutar la suite compilador O (-MO=C...) en un orden fijo después de módulo de inicialización (paquete de uso), y antes de que el programa principal, para ser capaz de almacenar el contexto de ejecución allí. Esto separa el tiempo de compilación (antes) del tiempo de ejecución (después). perl -c se detiene después de CHECK.

Como soy el mantenedor de los compiladores, utilizo CHECK y -MO = extensivamente. Mis métodos de módulos compile() son llamados por O dentro de un bloque CHECK. Con Od (depuración O) Llamo al método compile no en CHECK, pero más tarde en INIT, por lo que el depurador entra en él. El depurador no entra en los bloques CHECK por defecto, tiene que forzarlo con $DB::single=1 o usar Od.

UNITCHECK se agregó más tarde a la compilación y carga de módulos de grano fino, esp. .pmc archivos.

Nunca lo he usado hasta ahora. También puede suceder en tiempo de ejecución, por lo que podría usarlo para verificaciones de tipos de módulos cargados en tiempo de ejecución.

INIT se agregó para permitir la inicialización de clases separadas.

Raramente uso eso, pero es útil.

+0

Al parecer, te perdiste: "¿Alguna vez has usado CHECK, UNITCHECK o INIT? Si es así, ¿para qué? ¿Y un bloque BEGIN no hubiera sido suficiente por alguna razón?" Ese tipo de explicación delgada, el OP puede llegar a cualquier parte. – Axeman

Cuestiones relacionadas