检查列表是否为空 (Raku)

tin*_*ino 8 raku

FAQ:在 Raku 中如何检查列表是否为空?是否有比以下更惯用的方法:

my @l = ();
say @l.elems == 0;
say @l == ();
say @l.Bool;
Run Code Online (Sandbox Code Playgroud)

列表上文档推荐智能匹配

say $l ~~ ();
Run Code Online (Sandbox Code Playgroud)
  1. 你知道其他方法吗?
  2. () === ()即使"" === ""是正确的,您能否解释为什么 是错误的:我对此不清楚。

Jon*_*ton 11

其中建议:

say @l.elems == 0;
Run Code Online (Sandbox Code Playgroud)

这是一个很好避免的方法,因为它会强制对惰性列表中的所有元素进行评估(如果迭代器标记为惰性,则可能会导致异常,因为替代方法将一直运行,直到所有内存都用完为止)。

say @l == ();
Run Code Online (Sandbox Code Playgroud)

这有效,但具有与上述相同的问题。该==运营商的数字平等,所以它会迫使双方一个数字,然后对它们进行比较。这也归结为@l.elems(via. @l.Numeric)。你可以把这个形式写成更便宜的@l == 0,如果你真的想询问总共有多少个元素,这是最简洁的方式。

say @l.Bool;
Run Code Online (Sandbox Code Playgroud)

这更好,因为在惰性列表中,它最多只强制评估一个元素来回答问题。然而,这实际上与所问的相反:这是True如果数组不为空。像这样使用?!前缀运算符更自然:

say ?@l; # is not empty
say !@l; # is empty
Run Code Online (Sandbox Code Playgroud)

尽管很多时候你甚至都不需要做的是,因为事情好像ifunless提供布尔环境。因此可以写:

if @l { }        # not empty
unless @l { }    # empty
Run Code Online (Sandbox Code Playgroud)

这些可能是最好的方法。

至于其他建议:

say $l ~~ ();
Run Code Online (Sandbox Code Playgroud)

这很好,虽然可能比布尔化方法慢。

() === ()即使"" === ""是对的也是错的

那是因为List是引用类型,而不是值类型。由于()每次都构造一个不同的空列表,因此它们是不同的对象,因此将比较为不相同。您可以eqv改用:

say () eqv ()    # True
Run Code Online (Sandbox Code Playgroud)

但是不要用它来检查列表是否为空,因为它可能过于具体。例如:

my @l; say @l eqv ();    # False
my @l; say @l eqv [];    # True
Run Code Online (Sandbox Code Playgroud)

这是因为()is 是类型List,而 whilemy @l声明了一个Array. 通常,您不想关心真正存在的类型。

最后,关于这一行:

my @l = ();
Run Code Online (Sandbox Code Playgroud)

的赋值()毫无意义;my @a已经创建了一个空的Array. 事实上,这是一种很常见的代码味道,Comma IDE 对此给出了一个微弱的警告:

警告