检查列表是否为空 (Raku)

Check if a list is empty (Raku)

常见问题解答:在 Raku 中如何检查列表是否为空? 是否有比以下更惯用的方式:

my @l = ();
say @l.elems == 0;
say @l == ();
say @l.Bool;

doc on list recommends smartmatching

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

建议的人中:

say @l.elems == 0;

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

say @l == ();

这可行,但存在与上述相同的问题。 == 运算符是数值相等的,所以它会强制双方为一个数字,然后比较它们。这也归结为 @l.elems(通过 @l.Numeric)。您可以将这种形式写得更便宜,如 @l == 0,如果您真的想询问总共有多少个元素,这是最简洁的方法。

say @l.Bool;

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

say ?@l; # is not empty
say !@l; # is empty

尽管通常您甚至不需要,因为 ifunless 之类的东西提供了布尔上下文。因此可以这样写:

if @l { }        # not empty
unless @l { }    # empty

这些可能是最好的方法。

至于其他建议:

say $l ~~ ();

这很好,虽然可能比 boolification 方法慢。

() === () is wrong even if "" === "" is right

那是因为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。事实上,这是一种常见的代码味道,逗号 IDE 对此给出了一个微弱的警告: