class CallFrame {}

通常会使用 callframe 子例程从程序的当前状态捕获 CallFrame

my $frame = callframe;
say "The above line of code ran at {$frame.file}:{$frame.line}.";

如果没有参数,callframe 将为你提供调用 callframe 的行的帧信息。文件和行注释将与 $?FILE$?LINE 中的注释相同。

但是,你可以将一个数字传递给 callframe 以指定不同的帧级别。正数将向上移动帧级别。负数将向下移动到 callframe 方法和类本身,在它们运行以构造此信息时。

帧本身不一定只匹配方法或子例程调用。Raku 也为块等构造帧,因此,如果你需要特定方法调用的 callframe,请不要假设它是一个固定数量的向上级别。

每个帧都存储 注释,包括 文件 注释,这些注释具有用于直接访问它们的便捷方法。你还可以使用 code 方法检索对当前执行帧的代码块的引用。该帧还捕获帧中存储的所有词法变量,可以通过在帧对象上调用 my 来获取这些变量。

以下是一个简短的示例,它将找到调用例程并使用 callframe 接口打印调用者的包。

sub calling-frame() {
    for 1..* -> $level {
        given callframe($level-> $frame {
            when $frame ~~ CallFrame {
                    next unless $frame.code ~~ Routine;
                    say $frame.code.package;
                    last;
            }
            default {
                    say "no calling routine or method found";
                    last;
            }
        }
    }
}
 
calling-frame;

如果你只需要跟踪调用者信息,Backtrace 可能提供更好的获取信息的方法。CallFrame 包含有关特定帧的更多信息,但提供了一个繁琐的接口来枚举调用堆栈。

方法§

注意 从 6.d 版本开始,可以在 CallFrame 上调用 .raku(2019.11 版本之前的 .perl)。

方法代码§

method code()

返回当前块的可调用代码。当在 callframe(0) 返回的对象上调用时,这将与 &?BLOCK 中找到的值相同。

my $frame;
for ^3 { FIRST $frame = callframesay $_ * 3 };
say $frame.code()

在本例中,$frame 变量将保存循环中块的 Code

方法文件§

method file()

这是查找 file 注释的快捷方式。因此,以下代码打印 True

my $frame = callframe(0);
say $frame.file eq $frame.annotations<file>;

方法行§

method line()

这是查找 line 注释的快捷方式。例如,以下两个调用是相同的。

say callframe(1).line;
say callframe(1).annotations<line>;

方法注释§

method annotations()

返回一个包含调用者注释的 Map,即 linefile。获取注释信息的一种更简单的方法是使用其中一个便捷方法。

say callframe.annotations.^name;                   # OUTPUT: «Map␤» 
say callframe.annotations<file> eq callframe.file# OUTPUT: «True␤»

方法 my§

method my()

返回一个 Hash,其中命名了与帧词法作用域关联的所有变量及其值。

sub some-value {
    my $the-answer = 42;
    callframe(0);
}
 
my $frame = some-value();
say $frame.my<$the-answer># OUTPUT: «42␤»

例程§

子 callframe§

sub callframe(Int:D $level = 0)

返回给定级别的 CallFrame 对象。如果未给出级别,则默认级别为 0。正级别向上移动帧堆栈,负级别向下移动(进入对 callframe 的调用并更深入)。

如果给定级别的调用信息不存在,则返回 Mu。负级别可能会导致异常。

类型图§

CallFrame 的类型关系
raku-type-graph CallFrame CallFrame Any Any CallFrame->Any Mu Mu Any->Mu

展开上面的图表