【发布时间】:2020-03-25 22:17:12
【问题描述】:
FAQ:在 Raku 中如何检查列表是否为空? 还有比这更惯用的方法吗:
my @l = ();
say @l.elems == 0;
say @l == ();
say @l.Bool;
say $l ~~ ();
- 你知道其他方法吗?
- 即使
"" === ""是正确的,您能否解释为什么() === ()是错误的:我不清楚。
【问题讨论】:
标签: raku
FAQ:在 Raku 中如何检查列表是否为空? 还有比这更惯用的方法吗:
my @l = ();
say @l.elems == 0;
say @l == ();
say @l.Bool;
say $l ~~ ();
"" === "" 是正确的,您能否解释为什么() === () 是错误的:我不清楚。【问题讨论】:
标签: raku
建议的人中:
say @l.elems == 0;
这是一个很好的避免,因为它强制评估惰性列表中的所有元素(如果存在标记为惰性的迭代器,这可能会导致异常,因为替代方案将一直运行直到所有内存耗尽)。
say @l == ();
这可行,但有与上述相同的问题。 == 运算符是数字相等,因此它将强制双方为一个数字,然后比较它们。这也归结为@l.elems(通过。@l.Numeric)。你可以把这个表单写成@l == 0,这样更便宜,如果你真的想询问总共有多少个元素,这是最简洁的方法。
say @l.Bool;
这更好,因为在惰性列表中,它最多只强制评估一个元素来回答问题。但是,它实际上与所要求的相反:如果数组 not 为空,则为 True。像这样使用? 和! 前缀运算符更自然:
say ?@l; # is not empty
say !@l; # is empty
虽然您通常甚至不需要这样做,因为像 if 和 unless 这样的东西提供了一个布尔上下文。因此可以这样写:
if @l { } # not empty
unless @l { } # empty
这些可能是最好的方法。
关于其他建议:
say $l ~~ ();
这很好,但可能比布尔化方法慢。
() === ()是错误的,即使"" === ""是正确的
这是因为List 是引用类型,而不是值类型。由于() 每次都构造一个不同的空列表,它们是不同的对象,因此会比较为不相同。您可以改用eqv:
say () eqv () # True
但不要使用它来检查列表是否为空,因为它可能过于具体。例如:
my @l; say @l eqv (); # False
my @l; say @l eqv []; # True
这是因为() 是List 类型,而my @l 声明了Array。一般来说,您不需要关心真正存在的类型。
最后,关于这一行:
my @l = ();
() 的赋值是没有意义的; my @a 已经创建了一个空的 Array。事实上,Comma IDE 对此给出了一个弱警告:
【讨论】:
==,尽管这可能是因为两者都强制数字为 0。