问题
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 ~~ ();
- Do you know other ways ?
- 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