Wait the light to fall

Pair Constructor

焉知非鱼

Pair Constructor

又是一个来自 Damian 的好东西,真的是你所期待的对话者和解释者的好东西。

胖逗号运算符,=>,最初是用来分隔值的–但有一个变化。它的行为就像 , 运算符一样,但修改了解析,将左操作数字符串化。

它为你节省了一些字符串的引号,所以这个哈希初始化的代码。

my %h = (
    'a', 1,
    'b', 2,
);

可以被写为:

my %h = (
    a => 1,
    b => 2,
);

在这里,裸a和b的解析是正确的,不需要把它们引用成字符串。不过,通常的哈希赋值语义还是一样的:一对对的值会被逐一处理,鉴于 => 只是一个 “左侧字符串化"的逗号运算符,有趣的是,上面的代码就相当于这一块:

my %h = ( a => 1 => b => 2 => );

该提案建议改变这个"特殊"操作符的含义,使其成为一个新数据类型的构造函数, Pair:

一个 Pair 是由一个键和一个值构成的:

my @pairs = a => 42, 1 => 2;
say @pairs[0];           # a => 42
say @pairs[1];           # 1 => 2;
say @pairs[1].key.^name; # Int, not a Str

这里的 @pairs 列表只包含2个值,而不是4个,一个是方便我们串联的,第二个只是用裸的Int字面作为键。

事实证明,引入 Pair 不仅是一个方便操作的数据类型,这个变化还为…子程序提供了新的机会。

Raku 对签名的支持是一流的,这里既是为了 “第一旅行舱"的双关语,也是为了它的事情,是的,居然有 SignatureParameterCapture 作为一流的对象,这就可以有令人惊讶的解决方案。它支持命名参数,有大量的语法为它服务,这并不奇怪。而 Pair 类已经很自然地融入其中。

如果把 Pair 传给一个带有命名参数的子程序,其中键匹配,它就能正常工作,否则你就有一个 “完整"的 Pair,如果你想坚持,这里的一点语法可以帮助你。

sub foo($pos, :$named) {
    say "$pos.gist(), $named.gist()";
}

foo(42);                         # 42, (Any)
try foo(named => 42);            # Oops, no positionals were passed!
foo((named => 42));              # named => 42, (Any)
foo((named => 42), named => 42); # named => 42, 42

正如我们所看到的,设计一门语言是很有趣的:在一个部分所做的改变可能会对其他部分产生影响,而这些影响可能看起来很不相关,你最好希望你的选择在连接在一起的时候会有很好的效果。感谢 Damian 和所有参与 Raku 设计的人,感谢他们为之付出的巨大努力。

最后,但不是最不重要的:我们看到的 => 火车发生了什么?好了,现在它做什么你的意思,如果你的意思是它做什么。

my %a = a => 1 => b => 2;
say %a.raku; # {:a(1 => :b(2))}

是的,这是一个键a指向值对的1指向值对的b指向值对的2,所以至少这次的方向是不错的。祝大家好运,保持方向!