Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"isn't numeric" error in "sort" after "uniq"

Tags:

sorting

perl

uniq

use List::MoreUtils 'uniq';
print join ", ", sort uniq ("b", "a", "a");

results in Argument "a" isn't numeric in sort at ...

print join ", ", uniq sort ("b", "a", "a");

works as expected.

print join ", ", sort {$a cmp $b} uniq ("b", "a", "a");

works too - but what is the problem with the first example?

like image 255
André Avatar asked Aug 10 '19 18:08

André


1 Answers

That code falls under the sort invocation of

sort SUBNAME LIST

...
If SUBNAME is specified, it gives the name of a subroutine that returns an integer less than, equal to, or greater than 0 , depending on how the elements of the list are to be ordered.

The uniq in the first example is taken as a bareword that specifies the name of the sub to use for sorting and qw(b a a) is the list to sort -- you aren't uniq-ing the list (so to speak) but are using uniq as a sorting function for that list.

The error message comes as a sorting function needs to return a number and uniq returns strings.

You've discovered one way to make it work, and can also use the unary +

say for sort +uniq(@ary);    # or: say for sort + uniq @ary;

since what follows + is treated as an expression, so sort gets the evaluated list. See this post and this post for discussion of such uses of the unary +.

Or use parens through and through

say for sort (uniq(@ary));

Here the inner pair is also necessary since with sort (uniq @ary) the uniq is interpreted as a bareword in that list, thus out of place. Note that sort (uniq (@ary)) won't work since extra parens don't matter and we again have a bareword; so that space matters here!

This trickiness is due to sort's flexible (ambiguous) interface, taking a LIST optionally preceded by a bareword, which need be a sub name. It ends up relying on the interpreter to sort out some of that and then we have to be precise.

like image 148
zdim Avatar answered Nov 17 '22 13:11

zdim