gpt4 book ai didi

list - 如何在测试用例的多行列表初始化程序中获取当前行号?

转载 作者:行者123 更新时间:2023-12-05 00:47:56 24 4
gpt4 key购买 nike

有没有办法在 Perl 期间可靠地获取当前行号
未显式使用 __LINE__ 的多行列表赋值?我是
将测试用例存储在列表中,并希望用其行标记每个测试用例
number.* 这样我可以(大致)ok($_->[1], 'line ' . $_->[0]) for @tests .
而且,当然,与
__LINE__在每个测试用例的开头:) 。我有
无法找到这样做的方法,我遇到了一些caller 报告的行中的令人困惑的行为.

* 可能是 XY,但我找不到一个模块来做。

更新 我发现了一个 hack 并将其发布为 an answer .感谢@zdim 帮助我以不同的方式思考问题!

MCVE

很长,因为我尝试了几种不同的选择。 my_eval ,L() , 和 L2{}到目前为止我已经尝试过一些 - L()是那个
我最初希望会奏效。跳转到 my @testcases看看如何
我正在使用这些。测试时,请复制 shebang 行。

这是我的non-MCVE use case , 如果你感兴趣。

#!perl
use strict; use warnings; use 5.010;

# Modified from https://www.effectiveperlprogramming.com/2011/06/set-the-line-number-and-filename-of-string-evals/#comment-155 by http://sites.google.com/site/shawnhcorey/
sub my_eval {
my ( $expr ) = @_;
my ( undef, $file, $line ) = caller;
my $code = "# line $line \"$file\"\n" . $expr;

unless(defined wantarray) {
eval $code; die $@ if $@;
} elsif(wantarray) {
my @retval = eval $code; die $@ if $@; return @retval;
} else {
my $retval = eval $code; die $@ if $@; return $retval;
}
}

sub L { # Prepend caller's line number
my (undef, undef, $line) = caller;
return ["$line", @_];
} #L

sub L2(&) { # Prepend caller's line number
my $fn = shift;
my (undef, undef, $line) = caller;
return ["$line", &$fn];
} #L2

# List of [line number, item index, expected line number, type]
my @testcases = (
([__LINE__,0,32,'LINE']),
([__LINE__,1,33,'LINE']),
(L(2,34,'L()')),
(L(3,35,'L()')),
(do { L(4,36,'do {L}') }),
(do { L(5,37,'do {L}') }),
(eval { L(6,38,'eval {L}') }),
(eval { L(7,39,'eval {L}') }),
(eval "L(8,40,'eval L')"),
(eval "L(9,41,'eval L')"),
(my_eval("L(10,42,'my_eval L')")),
(my_eval("L(11,43,'my_eval L')")),
(L2{12,44,'L2{}'}),
(L2{13,45,'L2{}'}),
);

foreach my $idx (0..$#testcases) {
printf "%2d %-10s line %2d expected %2d %s\n",
$idx, $testcases[$idx]->[3], $testcases[$idx]->[0],
$testcases[$idx]->[2],
($testcases[$idx]->[0] != $testcases[$idx]->[2]) && '*';
}

输出

加上我的评论。
 0 LINE       line 32 expected 32
1 LINE line 33 expected 33

使用 __LINE__明确地工作正常,但我正在寻找一个
缩写。
 2 L()        line 45 expected 34 *
3 L() line 45 expected 35 *
L()使用 caller获取行号,稍后报告一行
在文件中 (!)。
 4 do {L}     line 36 expected 36
5 do {L} line 45 expected 37 *

当我包装 L()调用 do{} , caller返回正确的
行号——但只有一次(!)。
 6 eval {L}   line 38 expected 38
7 eval {L} line 39 expected 39

block eval ,有趣的是,工作正常。然而,它并没有更短
__LINE__ .
 8 eval L     line  1 expected 40 *
9 eval L line 1 expected 41 *

字符串 eval给出 eval 中的行号(没有惊喜)
10 my_eval L  line 45 expected 42 *
11 my_eval L line 45 expected 43 *
my_eval()是一个字符串 eval加上 #line指令基于 caller .它还在文件后面提供了一个行号(!)。
12 L2{}       line 45 expected 44 *
13 L2{} line 45 expected 45
L2L 相同,但它需要一个返回列表的 block ,
而不是
列表本身。它还使用 caller为行号。而且它
一次是正确的,但不是两次(!)。 (可能只是因为它是最后一个
项目— my_eval也报告了第 45 行。)

所以,这里发生了什么?我听说过 Deparse,想知道这是不是
优化相关,但我对引擎了解不够
从哪里开始调查。我也想这可以用源来完成
过滤器或 Devel::Declare ,但这远远超出了我的
经验等级。

拿 2

@zdim 的回答让我开始思考流畅的界面,例如 my answer :
$testcases2     # line 26
->add(__LINE__,0,27,'LINE')
->add(__LINE__,1,28,'LINE')
->L(2,29,'L()')
->L(3,30,'L()')
->L(3,31,'L()')
;

然而,即使那些在这里也不起作用——我得到第 26 行的每个 ->L()来电。所以看来 caller将所有链式调用视为来自 $testcases2->...线。那好吧。如果有人能启发我,我仍然想知道为什么!

最佳答案

caller只能得到语句的行号,在编译时决定。

当我将代码更改为

my @testcases;
push @testcases, ([__LINE__,0,32,'LINE']);
push @testcases, ([__LINE__,1,33,'LINE']);
push @testcases, (L(2,34,'L()'));
push @testcases, (L(3,35,'L()'));
...

维护行号,它可以工作(字符串评估除外)。

因此,在实际方面,使用 caller单独的调用语句很好。

Perl 内部结构

行号在编译时被烘焙到操作树中(我的重点)

At run-time, only the line numbers of statements are available [...]



来自 ikegami's post on permonks .

我们可以通过运行 perl -MO=Concise script.pl 看到这一点哪里行
2      nextstate(main 25 line_nos.pl:45) v:*,&,{,x*,x&,x$,$,67108864 ->3

is for the nextstate op, which sets the line number for caller (and warnings). See this post, and the nextstate example below.

A way around this would be to try to trick the compilation (somehow) or, better of course, to not assemble information in a list like that. One such approach is in the answer by cxw.

See this post for a related case and more detail.

nextstate example

Here's a multi-line function-call chain run through Deparse (annotated):

$ perl -MO=Concise -e '$x
->foo()
->bar()
->bat()'
d <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3 <=== the only nextstate
c <1> entersub[t4] vKRS/TARG ->d
3 <0> pushmark s ->4
a <1> entersub[t3] sKRMS/LVINTRO,TARG,INARGS ->b
4 <0> pushmark s ->5
8 <1> entersub[t2] sKRMS/LVINTRO,TARG,INARGS ->9
5 <0> pushmark s ->6
- <1> ex-rv2sv sKM/1 ->7
6 <#> gvsv[*x] s ->7
7 <.> method_named[PV "foo"] s ->8
9 <.> method_named[PV "bar"] s ->a
b <.> method_named[PV "bat"] ->c
-e syntax OK

即使连续的调用在不同的行上,它们也是同一个语句的一部分,所以都附加到同一个 nextstate .

关于list - 如何在测试用例的多行列表初始化程序中获取当前行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50510809/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com