给定单个参数,Array构造函数将其展平。这会导致问题:
my %hash = (a => 1; b => 2);
my @array = [ %hash ]; # result: [a => 1 b => 2], expected [{ a => 1, b => 2 }]List构造函数没有这个特性( single-argument rule),但不幸的是,没有用于创建单元素列表的简短语法:
List.new(%hash); # result is ({a => 1, b => 2}), as expected解决方法:如果参数是标量,它不会自动展平:
my $hash = %hash;
my @array = [ $%hash ]; # or my @array = [ $%hash ], or just my @array = $%hash
# result: [{a => 1, b => 2}], as expected另一种解决方法是在元素列表的末尾添加逗号:
my @array = [ %hash, ];真正的问题是当我们逐字写出数据时。如果1元素列表是扁平化的,那么在Perl6中表示类似JSON的嵌套结构就是一个真正的问题,而其他列表则不是。数据最终是错误的。在使用MongoDB时,我必须写出大量数据,因为MongoDB应用程序接口参数必须格式化为嵌套列表/数组。这几乎是不可能的。所以我问,展平单个数组元素的动机是什么?
发布于 2018-01-24 19:18:29
展平单个数组元素的动机是一致地应用单参数规则。数组构造函数[ ]也遵循单参数规则。也许将[%h]想象成circumfix:<[ ]>(%h)会有所帮助,但实际上确实是这样。如果您不想要扁平化,您可以逐项列出它(添加前缀$),或者,如您所示,添加一个逗号使其成为List。这遵循与$a相同的逻辑($a),但($a,)是一个只有一个元素$a的List。
my %h = a => 42, b => 666;
dd [%h]; # [:a(42), :b(666)]
dd [%h,%h]; # [{:a(42), :b(666)}, {:a(42), :b(666)}]
dd [%h,] # [{:a(42), :b(666)},] make it a List first
dd [$%h] # [{:a(42), :b(666)},] itemize the Hash发布于 2018-01-27 18:04:26
使用1-arg规则的数组构造运算符的动机:
其他期望潜在嵌套列表作为输入的运算符/关键字使用单参数规则-因此,为了保持一致性,此规则也适用。
通常使用1-arg规则进行列表转换运算符/关键字的动机:
运算符没有像函数一样的参数列表;它们只接受一个对象作为它们的参数(一元/外缀运算符),或者两边都有一个(二元运算符)。表达式@a,构造了一个单元素List,因此当将该表达式的结果传递给列表转换运算符时,它会像对待传递给它的任何其他非容器化List一样对待该Iterable:它会对其进行迭代,并根据参数在项目容器(即$变量)中包装时不会被迭代的事实进行操作,这是为了保留符号的单复数区别,正如@p6steve's answer所解释的那样。
下面是前面提到的一致性,使用一个关键字、一个二元运算符和一个外接运算符进行演示:
for @a { ... } # n iterations
for @a, { ... } # 1 iteration
for @a, @b { ... } # 2 iterations
for $a { ... } # 1 iteration
1..Inf Z @a # new Seq of n elements
1..Inf Z @a, # new Seq of 1 element
1..Inf Z @a, @b # new Seq of 2 elements
1..Inf Z $a # new Seq of 1 element
[ @a ] # new Array with n elements
[ @a, ] # new Array with 1 element
[ @a, @b ] # new Array with 2 elements
[ $a ] # new Array with 1 element子程序/方法呢?
它们确实有参数列表,所以单参数规则对它们来说并不像对运算符那样自然。
请注意,在参数列表的顶级作用域中,逗号并不创建List-它们分隔参数。
子例程/方法被认为是“列表转换”例程,期望潜在嵌套的列表作为输入,但仍然参与单参数规则,检查它们是获得一个参数还是多个参数,如果只有一个参数,则检查它是否包装在项目容器中:
map {...}, @a; # n iterations
map {...}, (@a,); # 1 iteration (Parens needed to get a List-constructing comma.)
map {...}, @a, @b; # 2 iterations
map {...}, $a; # 1 iteration用户定义的例程可以通过使用+@签名轻松地获得此行为。
发布于 2018-01-25 05:54:45
Perl中的@ sigil表示" The“,而$表示”the“。这种复数/单数的区别出现在语言中的不同地方,Perl中的许多便利都来自于此。扁平化是这样一种想法,即在某些上下文中,类似@的东西会自动将其值合并到周围的列表中。传统上,这既是Perl强大功能的来源,也是造成巨大混乱的原因。Perl 6在其发展过程中经历了许多与扁平化相关的模型,最后确定了一个简单的模型,称为“单参数规则”。
通过考虑for循环将执行的迭代次数,可以更好地理解单参数规则。要迭代的内容始终被视为for循环的单个参数,因此就是规则的名称。
for 1, 2, 3 { } # List of 3 things; 3 iterations
for (1, 2, 3) { } # List of 3 things; 3 iterations
for [1, 2, 3] { } # Array of 3 things (put in Scalars); 3 iterations
for @a, @b { } # List of 2 things; 2 iterations
for (@a,) { } # List of 1 thing; 1 iteration
for (@a) { } # List of @a.elems things; @a.elems iterations
for @a { } # List of @a.elems things; @a.elems iterations来自Synopsis7 https://design.raku.org/S07.html#The_single_argument_rule
https://stackoverflow.com/questions/48415323
复制相似问题