首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl 6数组构造函数平坦它的参数有什么合理的原因吗?

Perl 6数组构造函数平坦它的参数有什么合理的原因吗?
EN

Stack Overflow用户
提问于 2018-01-24 13:23:03
回答 3查看 343关注 0票数 14

给定单个参数,Array构造函数将其展平。这会导致问题:

代码语言:javascript
复制
my %hash = (a => 1; b => 2);
my @array = [ %hash ]; # result: [a => 1 b => 2], expected [{ a => 1, b => 2 }]

List构造函数没有这个特性( single-argument rule),但不幸的是,没有用于创建单元素列表的简短语法:

代码语言:javascript
复制
List.new(%hash); # result is ({a => 1, b => 2}), as expected

解决方法:如果参数是标量,它不会自动展平:

代码语言:javascript
复制
my $hash = %hash;
my @array = [ $%hash ]; # or my @array = [ $%hash ], or just my @array = $%hash
# result: [{a => 1, b => 2}], as expected

另一种解决方法是在元素列表的末尾添加逗号:

代码语言:javascript
复制
my @array = [ %hash, ];

真正的问题是当我们逐字写出数据时。如果1元素列表是扁平化的,那么在Perl6中表示类似JSON的嵌套结构就是一个真正的问题,而其他列表则不是。数据最终是错误的。在使用MongoDB时,我必须写出大量数据,因为MongoDB应用程序接口参数必须格式化为嵌套列表/数组。这几乎是不可能的。所以我问,展平单个数组元素的动机是什么?

EN

回答 3

Stack Overflow用户

发布于 2018-01-24 19:18:29

展平单个数组元素的动机是一致地应用单参数规则。数组构造函数[ ]也遵循单参数规则。也许将[%h]想象成circumfix:<[ ]>(%h)会有所帮助,但实际上确实是这样。如果您不想要扁平化,您可以逐项列出它(添加前缀$),或者,如您所示,添加一个逗号使其成为List。这遵循与$a相同的逻辑($a),但($a,)是一个只有一个元素$aList

代码语言:javascript
复制
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
票数 11
EN

Stack Overflow用户

发布于 2018-01-27 18:04:26

使用1-arg规则的数组构造运算符的动机:

  • ,因为它实际上只是一个外缀运算符,而不是特殊的语法。

其他期望潜在嵌套列表作为输入的运算符/关键字使用单参数规则-因此,为了保持一致性,此规则也适用。

通常使用1-arg规则进行列表转换运算符/关键字的动机:

  • 用于简化常见情况,即整个输入列表已存储在one variable中。
  • 用于避免进一步使用特殊大小写的文字逗号。

运算符没有像函数一样的参数列表;它们只接受一个对象作为它们的参数(一元/外缀运算符),或者两边都有一个(二元运算符)。表达式@a,构造了一个单元素List,因此当将该表达式的结果传递给列表转换运算符时,它会像对待传递给它的任何其他非容器化List一样对待该Iterable:它会对其进行迭代,并根据参数在项目容器(即$变量)中包装时不会被迭代的事实进行操作,这是为了保留符号的单复数区别,正如@p6steve's answer所解释的那样。

下面是前面提到的一致性,使用一个关键字、一个二元运算符和一个外接运算符进行演示:

代码语言:javascript
复制
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-它们分隔参数。

子例程/方法被认为是“列表转换”例程,期望潜在嵌套的列表作为输入,但仍然参与单参数规则,检查它们是获得一个参数还是多个参数,如果只有一个参数,则检查它是否包装在项目容器中:

代码语言:javascript
复制
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

用户定义的例程可以通过使用+@签名轻松地获得此行为。

票数 9
EN

Stack Overflow用户

发布于 2018-01-25 05:54:45

Perl中的@ sigil表示" The“,而$表示”the“。这种复数/单数的区别出现在语言中的不同地方,Perl中的许多便利都来自于此。扁平化是这样一种想法,即在某些上下文中,类似@的东西会自动将其值合并到周围的列表中。传统上,这既是Perl强大功能的来源,也是造成巨大混乱的原因。Perl 6在其发展过程中经历了许多与扁平化相关的模型,最后确定了一个简单的模型,称为“单参数规则”。

通过考虑for循环将执行的迭代次数,可以更好地理解单参数规则。要迭代的内容始终被视为for循环的单个参数,因此就是规则的名称。

代码语言:javascript
复制
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

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48415323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档