Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何(如果可能)将断点设置为特定的闭包?_Perl_Debugging_Closures - Fatal编程技术网

Perl 如何(如果可能)将断点设置为特定的闭包?

Perl 如何(如果可能)将断点设置为特定的闭包?,perl,debugging,closures,Perl,Debugging,Closures,当使用特定闭包的多个实例时,Perl调试器为每个实例列出相同的行号范围,而闭包实际上是不同的。 由于调试器的b命令的参数是行号,我想知道是否可以将断点设置为特定的闭包 考虑这个交互式示例: DB sub{my$s=$\[0];sub(){$s};} DB$s1=_s(1) DB$s2=_s(2) DB x$s1->() 0 1 DB x$s2->() 0 2 DB x$s1 0代码(0x55c7e8754958) ->&main::\uuuu ANON\uuuu在0中 DB x$s2 0代码

当使用特定闭包的多个实例时,Perl调试器为每个实例列出相同的行号范围,而闭包实际上是不同的。 由于调试器的
b
命令的参数是行号,我想知道是否可以将断点设置为特定的闭包

考虑这个交互式示例:

DB sub{my$s=$\[0];sub(){$s};}
DB$s1=_s(1)
DB$s2=_s(2)
DB x$s1->()
0  1
DB x$s2->()
0  2
DB x$s1
0代码(0x55c7e8754958)
->&main::\uuuu ANON\uuuu在0中
DB x$s2
0代码(0x55c7e8764990)
->&main::\uuuu ANON\uuuu在0中
因此,代码引用清楚地表明
$s1
$s2
是不同的。 现在,我可以在调用
$s1
时设置断点吗

注 我的第一个版本尝试了
subs($){…}
,导致
语法错误。。。(可能是失控的多行;;字符串从第2行开始)
尝试调用
s(1)
时。 因此,您似乎无法真正覆盖
s/old/new/
;-)

另一个音符 如果在一行上设置断点,如

my$checker=sub($){…};
在子例程中(在闭包中使用闭包),然后每次将
$checker
分配给时停止执行,但在调用闭包时不停止执行。 我的解决方法是像这样插入换行符(并将断点设置为
行):

my$checker=sub($){
...
};

根据您的问题,解决方案可能是创建一个“修饰”函数,设置一个固定断点(并将其分配回$s1)

DB sub{my$s=$\[0];sub(){$s};}
DB x$s1=_s(1)
0代码(0x55c7dc96b3a8)
->代码(0x55c7dc96b3a8)是否在???
DB x$s1_nob=$s1
0代码(0x55c7dc96b3a8)
->&main::\uuuu ANON\uuuu在0中
DB x$s1=sub{$DB::single=1;$s1_nob->()}
0代码(0x55c7dc9f1260)
->&main::(eval 30)[/usr/share/perl/5.26/perl5db.pl:738]:2]in(eval 30)[/usr/share/perl/5.26/perl5db.pl:738]:2-2
DB x$s1->()
main::CODE(0x55c7dc9f1260)((eval30)[/usr/share/perl/5.26/perl5db.pl:738]:
2:$s1=sub{$DB::single=1;$s1_nob->()};
DB s
0  1
似乎您(调试器)无法将断点设置为闭包,即使它有一个名称(继续问题中的代码):

DB*{main::xxx}=\u s(33)
DB x xxx
0  33
DB*{main::yyy}=\u s(44)
DB x yyy
0  44
DB b xxx
未找到子例程main::xxx。
DB x ref\&xxx
0“代码”
DB sub zzz(){22}####让我们与“常规”子例程进行比较
DB x zzz
0  22
DB x ref\&zzz
0“代码”

我想Perl需要一个增强请求。

根据@Georg Mavridis的回答,我尝试了以下方法:

  DB<1> sub _s($) { my $s = $_[0]; sub () { $s }; }

  DB<24> sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } }

  DB<27> x DEBUG(_s(1), 1)->()
main::CODE(0x5647d76c16d0)((eval 30)[/usr/lib/perl5/5.26.1/perl5db.pl:738]:2):
2:  sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } };
  DB<<28>> n
0  1
  DB<28> x DEBUG(_s(1), 0)->()
0  1
现在您使用第一个参数来定义单步执行,第二个参数是闭包,下面的参数将传递给闭包


但这仍然需要在调用闭包时修改代码(将
$f->($a,$b,$c)
替换为
DEBUG($d,$f,$a,$b,$c)
)。还是不漂亮。

这不太可能。从同一原型创建的所有闭包都共享同一个编译的操作树,并且它是操作树中设置断点的操作?如果是这样,您可以将行断点设置为那些非共享子节点。然而,当您想象共享闭包在不同类的十几个对象方法中使用时,这基本上意味着更改程序以进行调试。在另一个函数中包装我要研究的函数并重新分配它。顺便说一句,在创建位置设置断点并分配装饰器也可以完成这项工作。
  DB<1> sub _s($) { my $s = $_[0]; sub () { $s }; }

  DB<24> sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } }

  DB<27> x DEBUG(_s(1), 1)->()
main::CODE(0x5647d76c16d0)((eval 30)[/usr/lib/perl5/5.26.1/perl5db.pl:738]:2):
2:  sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } };
  DB<<28>> n
0  1
  DB<28> x DEBUG(_s(1), 0)->()
0  1
  DB<7> sub DEBUG($$;@) { my ($d, $f, @args) = @_; $DB::single = $d; $f->(@args) }

  DB<8> x DEBUG(1, _s(42))
main::DEBUG((eval 12)[/usr/lib/perl5/5.26.1/perl5db.pl:738]:2):
2:  sub DEBUG($$;@) { my ($d, $f, @args) = @_; $DB::single = $d; $f->(@args) };
  DB<<9>> n
0  42
  DB<9> x DEBUG(0, _s(42))
0  42