任何人都可以解释这段代码如何打印输出?
#!/usr/bin/perl
use warnings;
use strict;
my
($j,$
a,$p,$h);$
j=sub{print(
chr($p+=$a->[$
h++]));$j};;;$a
=[0, split
"[: \n]+",
q/43 -002:1
-084 065:13
0001 000005
-0012 -00003
000013 -82 00048
21:13:-6.00:-76:72
-007.:02:00008.00
:::-6.00:::013
-70:3::-70:.64
/];$p=0x4a
;;$h=0;
$j->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->();
Just another perl hacker
答案 0 :(得分:6)
这实际上是一个相当简单的JAPH。它的两个最大特点是分割构成大部分"图像"和半递归打印的数据字符串。
这是我清理格式时得到的代码
my ($j,$a,$p,$h);
$j = sub {
print( chr( $p += $a->[$h++] ) );
$j
};
;;
$a = [0, split "[: \n]+", # the split regex
q/43 -002:1 # input string start: q/ ...
-084 065:13
0001 000005
-0012 -00003
000013 -82 00048
21:13:-6.00:-76:72
-007.:02:00008.00
:::-6.00:::013
-70:3::-70:.64
/]; # input string end: .../
# print Dumper $a; # <--- this is my line
$p = 0x4a;;
$h=0;
$j->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->();
第一部分是4个主要变量的声明和分配:
$j
是打印字符的代码引用,然后返回对自身的引用。印刷品包括几个步骤:
$a->[$h++]
遍历@$a
数组,返回一个元素$p += ...
该元素已添加到$p
print chr( $p ... )
然后将$p
返回到chr()并打印生成的字符。子块中的最后一个是$j
,这意味着每次迭代时,sub的返回值将是对它自己的引用。这是允许半递归功能的部分。
$a
是对数组的引用,该数组由0和输入字符串上的拆分结果组成。在这里,一行代码中也发生了一些事情:
q/43 .../
这是带有分隔符斜杠q()
的常规/
单引号字符串。它在表示数组引用的右括号]
之前结束。split "[: \n]+",
这是对字符类的拆分,重复1次或更多次。其中有额外的空间(我已经删除了这里)来填充JAPH本身的空间。基本上这将删除所有冒号,空格和换行符并返回结果列表。 $a = [0, ... ]
将拆分列表添加到0
列表中(只有一个元素),所有内容都用括号括起来表示数组引用,然后将其存储在{{1}中}。 我认为该列表以$a
开头,因为代码有一次性错误,因为0
的原始值是输出中的第一个字母。
这是$p
的{{1}}输出:
Data::Dumper
$a
和$VAR1 = [
0,
'43',
'-002',
'1',
'-084',
'065',
'13',
'0001',
'000005',
'-0012',
'-00003',
'000013',
'-82',
'00048',
'21',
'13',
'-6.00',
'-76',
'72',
'-007.',
'02',
'00008.00',
'-6.00',
'013',
'-70',
'3',
'-70',
'.64'
];
只是数字,它们在此中的作用是$p
函数的源编号和$h
数组的迭代器。
最后一行是运行chr()
子例程并打印JAPH的部分。链式@$a
语法意味着每个先前迭代的返回值用于下一次执行。并且$j
返回对自身的引用,这使得它成为半递归事件,只有值发生变化。
我想这与此相似:
->()
让我们逐步完成前几个步骤
$j
执行$x = $j->();
$y = $x->();
$z = $y->();
...
$j->()
递增为1,返回0到$a->[$h++]
子行程,返回$h
的第一个元素,即$a
。< / LI>
$a
此0
已添加到$p += 0
,这会将0
(74)的值返回给chr $p
现在会将$p
打印到标准输出print chr(74)
已退回。J
对返回值执行另一次执行,因此再次运行$j
。->()
$j
增加到2,返回1到$a->[$h++]
,返回第二个元素$h
。$a
74 + 43 = 117返回43
$p += 43
这会打印chr
print chr(117)
的元素既有正面也有负面,将数字移动到需要的位置。最后,所有打印的字母均为u
以下是10次首次执行的简要说明:
$a
答案 1 :(得分:5)
使用perl -MO=Deparse
运行它以查看Perl看到的内容:
use warnings;
use strict 'refs';
my($j, $a, $p, $h);
$j = sub {
print chr($p += $$a[$h++]);
$j;
}
;
$a = [0, split(/[: \n]+/, "43 -002:1\n-084 065:13\n0001 000005\n-0012 -00003\n000013 -82 00048 \n21:13:-6.00:-76:72 \n -007.:02:00008.00 \n :::-6.00:::013 \n -70:3::-70:.64 \n ", 0)];
$p = 74;
$h = 0;
&$j()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->();
基本上,$j
是一个子引用,它返回另一个子引用,依此类推。在返回之前,它会打印一个字符并将“指针”移动到要打印的字符数组中。
答案 2 :(得分:1)
小评论。
数字块中的最后一行应为此
-68:3::-70:.64
而不是
-70:3::-70:.64
打印一段时间需要-68,-70打印一个逗号。
(该行的其余部分,“:3 :: - 70:.64”只是噪音。这些数字永远不会传递给$ j中的匿名函数。)