Check if a list is empty (Raku)

血红的双手。 提交于 2020-04-12 20:23:46

问题


FAQ: In Raku how to check if a list is empty ? Are there more idiomatic ways than:

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

The doc on list recommends smartmatching

say $l ~~ ();
  1. Do you know other ways ?
  2. Can you explain why () === () is wrong even if "" === "" is right: I'm not clear on that.

回答1:


Of those suggested:

say @l.elems == 0;

This is a good one to avoid, because it forces evaluation of all elements in a lazy list (which may lead to an exception if there are iterators marked as lazy, since the alternative would be running until all memory is exhausted).

say @l == ();

This works, but has the same problem as above. The == operator is numeric equality, and so it will coerce both sides to a number and then compare them. That also boils down to @l.elems (via. @l.Numeric). You could write this form cheaper as @l == 0, which is the neatest way if you really do want to ask for how many elements there are in total.

say @l.Bool;

This is better, because in a lazy list it only forces evaluation of one element at most to answer the question. However, it's actually the inverse of what was asked: this is True if the array is not empty. It's more natural to use the ? and ! prefix operators like this:

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

Though often you don't even need to do that, because things like if and unless provide a boolean context. Thus one could write:

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

These are probably the best ways.

As to other suggestions:

say $l ~~ ();

This is fine, though probably slower than the boolification approach.

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

That's because List is a reference type, not a value type. Since () constructs a distinct empty list each time, they are distinct objects, and so will compare as non-identical. You can use eqv instead:

say () eqv ()    # True

But don't use this to check if a list is empty, because it's probably overly specific. For example:

my @l; say @l eqv ();    # False
my @l; say @l eqv [];    # True

This is because () is of type List, while my @l declares an Array. In general, you don't want to care what type is really there.

Finally, about this line:

my @l = ();

The assignment of () is pointless; my @a already creates an empty Array. In fact, it's a common enough code smell that Comma IDE gives a weak warning about this:



来源:https://stackoverflow.com/questions/60858190/check-if-a-list-is-empty-raku

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!