这实际上是一个相当简单的 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
$j 是一个代码引用,它打印一个字符,然后返回对自身的引用。打印包括几个步骤:
-
$a->[$h++] 遍历 @$a 数组,返回一个元素
-
$p += ... 该元素被添加到 $p
-
print chr( $p ... ) 然后 $p 返回到 chr() 并打印结果字符。
sub 块的最后一个是$j,表示每次迭代,sub 的返回值都会是对自身的引用。这是允许半递归功能的部分。
$a
$a 是对包含 0 和输入字符串拆分结果的数组的引用。一行代码中还发生了一些事情:
-
q/43 .../ 这是带有分隔符斜杠 / 的常规 q() 单引号字符串。它在右括号 ] 之前结束,表示数组引用。
-
split "[: \n]+", 这是对字符类的拆分,重复 1 次或多次。它里面有额外的空间(我在这里删除了)来填充 JAPH 本身的空间。基本上这会删除所有冒号、空格和换行符并返回结果列表。
-
$a = [0, ... ] 拆分列表被添加到0 列表中(只有一个元素),所有内容都用括号括起来表示数组引用,然后将其存储在$a 中。
我假设列表以0 开头,因为代码有一次性错误,$p 的原始值是输出中的第一个字母。
这是$a 的Data::Dumper 输出:
$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
$p 和$h 只是数字,它们在其中的作用分别是chr() 函数的源编号和@$a 数组的迭代器。
最后一行是运行$j 子例程并打印JAPH 的部分。链式->() 语法意味着每次前一次迭代的返回值用于下一次执行。并且$j 返回一个对自身的引用,这使得它成为一个半递归的事情,只有值改变。
我猜它类似于这样做:
$x = $j->();
$y = $x->();
$z = $y->();
...
让我们来看看前几个步骤
-
$j->()执行
-
$a->[$h++] $h 递增到 1,返回 0 到 $a 子带,它返回 $a 的第一个元素,即 0。
-
$p += 0 这个0 被添加到$p,这会将$p (74) 的值返回给chr
-
print chr(74) 现在将 J 打印到标准输出
-
$j 被返回。
-
->()对返回值又执行一次,所以$j再次运行。
-
$a->[$h++] $h 递增到 2,返回 1 到 $a,后者返回第二个元素 43。
-
$p += 43 74 + 43 = 117 返回到chr
-
print chr(117) 这个打印 u
$a 的元素有正有负,将数字移动到需要的位置。最后,所有的字母都打印出来了:Just another Perl hacker,
以下是前 10 次处决的概要:
p => 74 += 0 = 74 output => chr( 74) J
p => 74 += 43 = 117 output => chr(117) u
p => 117 += -002 = 115 output => chr(115) s
p => 115 += 1 = 116 output => chr(116) t
p => 116 += -084 = 32 output => chr( 32)
p => 32 += 065 = 97 output => chr( 97) a
p => 97 += 13 = 110 output => chr(110) n
p => 110 += 0001 = 111 output => chr(111) o
p => 111 += 000005 = 116 output => chr(116) t
p => 116 += -0012 = 104 output => chr(104) h