没有明确使用__LINE__的多行列表分配?我是
将测试用例存储在列表中,并希望用它的行标记每个测试用例
数字.*那样我可以(粗略地)
对于@tests,确定($_-> [1],’line’.$_-> [0]).
而且,当然,我想保存打字比较
将__LINE__放在每个测试用例的开头:).我有
找不到办法,我遇到了一些
调用者报告的行中令人困惑的行为.
*可能的XY,但我找不到一个模块来做它.
更新我发现了一个hack并将其发布为an answer.感谢@zdim帮助我以不同的方式思考问题!
MCVE
很长一段,因为我尝试了几种不同的选择. my_eval,
L()和L2 {}是我迄今为止尝试的一些 – L()就是那个
我最初希望能工作.跳到我的@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,&$fn]; } #L2 # List of [line number,item index,expected line number,type] my @testcases = ( ([__LINE__,32,'LINE']),([__LINE__,1,33,(L(2,34,'L()')),(L(3,35,(do { L(4,36,'do {L}') }),(do { L(5,37,(eval { L(6,38,'eval {L}') }),(eval { L(7,39,(eval "L(8,40,'eval L')"),(eval "L(9,41,(my_eval("L(10,42,'my_eval L')")),(my_eval("L(11,43,(L2{12,44,'L2{}'}),(L2{13,45,); 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()使用调用者来获取行号,并在以后报告一行
在文件(!)中.
4 do {L} line 36 expected 36 5 do {L} line 45 expected 37 *
当我在do {}中包装L()调用时,调用者返回正确的
行号 – 但只有一次(!).
6 eval {L} line 38 expected 38 7 eval {L} line 39 expected 39
有趣的是,块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指令
呼叫者.它还在文件后面给出一个行号(!).
12 L2{} line 45 expected 44 * 13 L2{} line 45 expected 45
L2与L相同,但它需要一个返回列表的块,
而不是
清单本身.它还使用呼叫者作为行号.它
是正确的,但不是两次(!). (可能只是因为它是最后一次
item – my_eval也报告第45行.)
那么,这里发生了什么?我听说过Deparse并想知道这是不是
优化相关,但我不知道引擎知道
从哪里开始调查.我也想象这可以用来源完成
过滤器或Devel::Declare
,但这远远超出我的
经验等级.
拿2
@ zdim的回答让我开始考虑流畅的界面,例如,在my answer:
$testcases2 # line 26 ->add(__LINE__,27,'LINE') ->add(__LINE__,28,'LINE') ->L(2,29,'L()') ->L(3,30,31,'L()') ;
但是,即使那些在这里不起作用 – 我为每个 – > L()调用得到第26行.因此看起来调用者将所有链接的调用视为来自$testcases2-> …行.那好吧.我仍然有兴趣知道为什么,如果有人可以开导我!
解决方法
当我将代码更改为
my @testcases; push @testcases,'LINE']); push @testcases,'L()')); push @testcases,'L()')); ...
保持行号,它有效(除了字符串evals).
在编译时将行号烘焙到op-tree中(我的重点)
At run-time,only the line numbers of statements are available […]
我们可以通过运行perl -MO = Concise script.pl来看到这一点
2 nextstate(main 25 line_nos.pl:45) v:*,&,{,x*,x&,x$,$,67108864 ->3
用于nextstate op,它设置调用者(和警告)的行号.见this post.
然后解决这个问题的方法是尝试欺骗编译(“某种程度上”),或者更好的是,不要在这样的列表中组装信息.其中一种方法是在answer by cxw.
有关相关案例和更多详细信息,请参阅this post.