3
print$f+=$z=$f-$z,$/for--$z..8

或者,如果您将 $z 替换为 $!,您可以执行以下操作。

print$f+=$!=$f-$!for--$!..8

但为什么?$!是错误 perlval,不是吗?

4

2 回答 2

10

如果我们添加一些空间以使其更具可读性:

print $f += $z = $f - $z ,$/ for --$z .. 8

让我们将不同的部分提取到普通代码中。首先,使用常规for循环。

for (--$z .. 8) {
     print $f += $z = $f - $z ,$/
}

前缀-- 自动减量运算符将采用未初始化的变量$z,将其强制转换为 0,减去 1,然后返回-1-1这与分配给基本相同$z

我们从 -1 循环到 8。这些数字无关紧要,因为它们被分配给$_,而从未使用过。基本上我们只循环 10 步。此步骤中使用的变量无关紧要。它可以是任何可以分配的变量,这就是为什么$!——操作系统错误变量也可以工作。

我们可以将语句简化为

$z = -1;
for (0 .. 9)

print 语句基本上打印了两件事:

$f += $z = $f - $z

$/

用逗号分隔的两个语句,,表示它是一个列表。预定义变量$/输入记录分隔符;默认情况下它是换行符(取决于操作系统)。print接受一个参数列表,这就是它的工作方式。print与自动换行相同say。所以我们可以交换它并将代码简化为:

say $f += $z = $f - $z

让我们解开那个任务。它基本上是两条语句,从右到左依次完成,以打印结束:

$z = $f - $z
$f += $z
say $f

如果我们把它放在一起,我们得到:

$z = -1;
for (0 .. 9) {       # loop 10 times
    $z = $f - $z;    # calculate increment
    $f += $z;        # increment value
    say $f;          # print value
}

它是这样工作的:

我们知道$z最初是-1来自for循环。并且由于$f从未使用过,它将是未定义的(在减法上下文中使用时将被强制转换为 0)。所以我们得到:

$z = $f - $z = undef - (-1) = 0 + 1 = 1
$f += $z = 1 => $f = $f + 1 => $f = 1

所以第一个循环迭代打印 1. Next turn

$z = $f - $z = 1 - 1 = 0
$f += $z = 0 => $f = $f + 0 = 1 + 0 = 1

下一个打印也是 1。下一回合

$z = $f - $z = 1 - 0 = 1
$f += $z = 1 => $f = $f + 1 = 1 + 1 = 2

等等。

于 2021-06-20T12:40:18.633 回答
1

This is an obfuscation. It works because (from perlvar):

$ERRNO $!

When referenced, $! retrieves the current value of the C errno integer variable. If $! is assigned a numerical value, that value is stored in errno. When referenced as a string, $! yields the system error string corresponding to errno.

For example,

$ perl -M5.010 -e'
   $! = 2;
   say 0+$!;    # Treat as number
   say "$!";    # Treat as string

   $! = 3;
   say 0+$!;
   say "$!";
'
2
No such file or directory
3
No such process
于 2021-06-20T12:15:53.613 回答