Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
691 views
in Technique[技术] by (71.8m points)

perl - why does sort with uniq not work together

I have the following script:

use strict;
use List::MoreUtils qw/uniq/;
use Data::Dumper;

my @x = (3,2);
my @y = (4,3);

print "unique results 
";
print Dumper([uniq(@x,@y)]);

print "sorted unique results
";
print Dumper([sort uniq(@x,@y)]);

The output is

unique results 
$VAR1 = [
          3,
          2,
          4
        ];
sorted unique results
$VAR1 = [
          2,
          3,
          3,
          4
        ];

So it looks that sort does not work with uniq. I did not understand why.

I ran the perl script with -MO=Deparse and got

use List::MoreUtils ('uniq');
use Data::Dumper;
use strict 'refs';
my(@x) = (3, 2);
my(@y) = (4, 3);
print "unique results 
";
print Dumper([uniq(@x, @y)]);
print "sorted unique results
";
print Dumper([(sort uniq @x, @y)]);

My interpretation is that perl decided to remove the parentheses from uniq(@x,@y) and using uniq as a function of sort.

Why did perl decide to do it?

How can i avoid these and similar pitfalls?

Thanks, David

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The sort builtin accepts a subroutine name or block as first argument which is passed two items. It then must return a number which determines the order between the items. These snippets all do the same:

use feature 'say';
my @letters = qw/a c a d b/;

say "== 1 ==";
say for sort @letters;

say "== 2 ==";
say for sort { $a cmp $b } @letters;

say "== 3 ==";
sub func1 { $a cmp $b }
say for sort func1 @letters;

say "== 4 ==";
sub func2 ($$) { $_[0] cmp $_[1] }  # special case for $$ prototype
say for sort func2 @letters;

Notice that there isn't any comma between the function name and the list, and note that the parens in Perl are primarly used to determine precedence – sort func1 @letters and sort func1 (@letters) are the same, and neither executes func1(@letters).

To disambiguate, place a + before the function name:

sort +uniq @letters;

To avoid such unexpected behaviour, the best solution is to read the docs when you aren't sure how a certain builtin behaves – unfortunately, many have some special parsing rules.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...