8

autodie根据文档,编译指示(如)是词法范围的。

{
use autodie;
  ..
  ..
}
# Can die here

这是否适用于所有加载的模块use?据我所知,use几乎与以下内容相同:

BEGIN {
  require autodie;
  autodie->import(LIST);
}

BEGIN发生在编译时,并且 require 没有词法范围。那么如何autodie知道它的范围呢?

4

3 回答 3

11

The short answer is that lexically-scoped pragmatic modules are explicitly written to behave that way, and use the magical internal variables $^H and %^H during compile time to enable and disable features.

The compiler plays its part by implicitly localising these variables so their value is restored at the end of compiling a code block to what it was at the start. In that way it provides the basis of lexical semantics.

Originally only the $^H variable was available. It contains a bit mask that dictates which compiler options are available at any time during the compilation. Because of that the only lexical pragmas that could be written were ones that manipulated the defined set of magic bits in $^H.

Later the %^H hash was introduced, and any pragma can now store values in this hash with keys that start with the name of the pragma. Because the compiler localises the hash in the same way as the scalar, any pragma can store automatically scoped status information here.

The autodie module doesn't manipulate either of these variables, but subclasses the Fatal module which does all the hard work. It uses %^H to keep track of which operators have been made fatal, and relies on the compiler to discard this information at the end of the block.

于 2012-07-29T19:23:01.737 回答
8

Fatal.pm从作为后端的导入方法中autodie,享受一下:

# Dark magic to have autodie work under 5.8
# Copied from namespace::clean, that copied it from
# autobox, that found it on an ancient scroll written
# in blood.

# This magic bit causes %^H to be lexically scoped.
$^H |= 0x020000;

所以答案是确实有一种方法可以让你的导入知道它们的词法范围,但它与 perl 的核心深深纠缠在一起,并不适合普通程序员使用。

于 2012-07-29T19:08:48.520 回答
1

It's not require that's interesting; it's what the pragma does in import.

Most (all?) pragmas use $^H or %^H. The parser localises these to the scope being parsed, meaning it restores them to the value they had before

Take strict, for example. Its import modifies $^H. $^H contains a series of flags that instructs the compiler how to behave.

$ perl -e'
    BEGIN { printf "%04X\n", $^H }
    {
       use strict;
       BEGIN { printf "%04X\n", $^H }
    }
    BEGIN { printf "%04X\n", $^H }
'
0100
0702
0100

$^H is reserved for Perl's usage, but similarly localised %^H is available for general use. For example, feature::qw_comment hooks into the parser once, when it's loaded by require, but doesn't do anything unless $^H{'feature::qw_comments::'} is true. It's import is equivalent to

sub import { $^H{'feature::qw_comments::'} = 1; }
于 2012-07-30T01:13:21.677 回答