开发者

What is the usefulness of CHECK, UNITCHECK and INIT blocks in Perl?

开发者 https://www.devze.com 2022-12-10 16:03 出处:网络
I know what they all do, but have never found myself in a 开发者_C百科situation where I\'ve needed any of them. I\'ve used BEGIN blocks on many occasions and ENDs once in a while. BEGIN is especially

I know what they all do, but have never found myself in a 开发者_C百科situation where I've needed any of them. I've used BEGIN blocks on many occasions and ENDs once in a while. BEGIN is especially useful when you need to tweak the environment before code gets run, and I've used END in certain debugging situations to trap important state information for hard-to-track-down fatal errors.

Have you ever used CHECK, UNITCHECK or INIT? If so, what for? And would a BEGIN block not have sufficed for some reason?

The documentation for the blocks is on PerlDoc.


An interesting use of CHECK blocks is in "Advanced Perl programming" by Simon Cozens (O'Reilly) in Chapter 1, in "Doing things later with CHECK" section. He shows how to implement "final" java-like attribute

Also, Devel::Sub::Trace uses INIT blocks to incert traces (this info is from POD for Devel::Hook which is a module used for working with those named blocks)


I had a package import function which would do some heavy duty processing and then make an eval call. How do you debug something like that? The import function gets run when you use the module, which takes place at compile time (like it was inside a BEGIN block). For some reason (I think it was because I needed to pass parameters to import with heredoc notation, but it could have been something else), it wasn't good enough to say require Module; Module->import(@args).

So my workaround was to build the string for eval in import, and save it another variable. Then I ran the eval in an INIT block. When you ran the debugger, the very first execution point was at the start of the INIT block and I could use the debugger to step through the eval statement.


Well BEGIN blocks are run at compile time, as you know. So I keep it to code that needs to be run in order for my module to be imported.

I wrote a script wrapper, to do everything that was being done in boilerplate code that occurred in a couple hundred scripts.

  • There were things I had to do to get the module reading to be use-d. That I ran in BEGIN blocks and import sub.
  • But there was also all that boilerplate that initialized the services the script would use. Therefore, I ran these actions in the INIT blocks.
  • And ran necessary cleanup and exit code in the END blocks.

I think CHECK makes sense if you write modules with XS engines, but I have only used it a handful of times. One time I think it was to check out the suggestions in Intermediate Perl. And I can't offhand remember the other reasons.

But I use INIT blocks when I feel that code is more part of the script, than setting up the module. In essence, I only do what is necessary during compile time.


perlmod explains those special blocks but indeed only BEGIN and END are commonly used. They are just arrays of CVs, LIFO or FIFO. Those blocks allow seperate timings when code is run, independent on the location in the source file. So you can keep code sections together, but they are executed at different times (PHASES).

CHECK was added initially to run the compiler suite O (-MO=C...) in a fixed order after module initialization (use package), and before the main program, to be able store the execution context there. This seperates compile-time (before) from run-time (after). perl -c stops after CHECK.

As I am the maintainer of the compilers, I use CHECK and -MO= extensively. My modules compile() methods are called by O within a CHECK block. With Od (debugging O) I call the compile method not in CHECK, but later in INIT, so the debugger steps into it. The debugger does not step into CHECK blocks per default, you have to force it with $DB::single=1 or use Od.

UNITCHECK was added later to fine-grain module compilation and loading, esp. .pmc files.

I've never used that so far. It can also happen at run-time, so I might use it for type checks of run-time loaded modules.

INIT was then added to allow seperate class initialization.

I rarely use that, but it is handy.

0

精彩评论

暂无评论...
验证码 换一张
取 消