【问题标题】:Trouble with shift and dereference operator移位和取消引用运算符的问题
【发布时间】:2014-05-29 15:55:47
【问题描述】:

我有一个关于如何评估-> 运算符的左侧和右侧的问题。考虑以下代码:

#! /usr/bin/perl

use strict;
use warnings;
use feature ':5.10';

$, = ': ';
$" = ', ';

my $sub = sub { "@_" };

sub u { shift->(@_) }
sub v { my $s = shift; $s->(@_) }

say 'u', u($sub, 'foo', 'bar');
say 'v', v($sub, 'foo', 'bar');

输出:

u: CODE(0x324718), foo, bar
v: foo, bar

我希望 u 和 v 行为相同,但事实并非如此。我总是假设 perl 在这些情况下从左到右评估事情。像shift->another_method(@_) 甚至shift->another_method(shift, 'stuff', @_) 这样的代码很常见。

如果第一个参数恰好是代码引用,为什么会中断?我在这里是在未定义/未记录的领域吗?

【问题讨论】:

  • 这只是部分答案:虽然只有一个 -> 运算符记录在案,但 ->()->[]->{}->method 实际上是作为完全不同的运算符实现的。跨度>
  • @RobEarl,我的回答是在方法调用之前评估参数(这很简单),而不是在 LHS 之前。即使->() 的工作方式与方法调用相同,这在这里也无济于事。
  • @RobEarl,有趣的是,->method(@args) 的 LHS 在 args 之前被评估,所以shift->foo(@_) 确实按预期工作! (可能是因为定期做这件事很诱人,所以值得额外使用前端堆栈。)

标签: perl


【解决方案1】:

->() 的操作数计算顺序未记录。它恰好在 LHS 之前评估参数(分别在下面的第 3-4 行和第 5 行)。

>perl -MO=Concise,u,-exec a.pl
main::u:
1  <;> nextstate(main 51 a.pl:11) v:%,*,&,x*,x&,x$,$,469762048
2  <0> pushmark s
3  <#> gv[*_] s
4  <1> rv2av[t2] lKM/3
5  <0> shift s*
6  <1> entersub[t3] KS/TARG,2
7  <1> leavesub[1 ref] K/REFC,1
a.pl syntax OK

在同一个表达式中使用和修改变量可能很危险。除非您能解释以下内容,否则最好避免:

>perl -E"$i=5; say $i,++$i,$i"
666

你可以使用

$_[0]->(@_[1..$#_])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2023-02-15
    • 2016-10-16
    相关资源
    最近更新 更多