2013-11-27 3 views
6

Я следующий сценарий:почему-то с Uniq не работают вместе

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

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

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

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

Выход

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

Так это выглядит, что-то не работает с Uniq. Я не понимал, почему.

Я запускал скрипт на языке Perl с -MO = Deparse и получил

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

Моя интерпретация, что Perl решил удалить скобки из Uniq (@ х, @ Y) и с использованием Uniq в зависимости от вида ,

Почему perl решил сделать это?

Как я могу избежать этих и подобных подводных камней?

Спасибо, David

ответ

7

sort builtin принимает имя подпрограммы или блок в качестве первого аргумента который передается двумя пунктами. Затем он должен вернуть число, которое определяет порядок между элементами. Эти фрагменты все делают то же самое:

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; 

Обратите внимание, что не существует какой-либо запятая между именем функции и списком, и обратите внимание, что круглые скобки в Perl являются прежде всего органов используются для определения приоритета - sort func1 @letters и sort func1 (@letters) одинаковы , и ни один из них не выполняет func1(@letters).

Для неоднозначность, поместите + перед именем функцию:

sort +uniq @letters; 

Чтобы избежать такого неожиданного поведения, то лучшим решением будет читать документы, когда вы не уверены в том, как некий встроенный ведет себя, - к сожалению, у многих есть специальные правила синтаксического анализа.

+0

Я не понял на 100 процентов, почему он не выполняет uniq заранее, а затем использует сортировку LIST, но я предполагаю, что он предпочитает форму SUBNAME LIST. Что означает знак +? –

+1

@DavidMichaelGang да, проблема в том, что ваш код анализировался как «сортировать SUBNAME LIST». Унарный '+' запрещает эту интерпретацию и заставляет «нормальный» вызов 'uniq'. Важно помнить, что 'sort' не является подпрограммой - это ключевое слово, как' foreach' или 'grep'. – amon

+0

'DWIM' терпит неудачу, так как можно было бы ожидать такого же поведения, как для' sort grep' или 'sort map' –

3

Вы можете поместить скобку Arround в Uniq fonction:

print Dumper([sort (uniq(@x,@y))]); 

выход:

$VAR1 = [ 
      2, 
      3, 
      4 
     ]; 
+0

Да. Это могло бы решить это, но мой вопрос в том, почему perl работает таким образом. –

+1

Он просто делает. Некоторые фрагменты синтаксиса Perl неоднозначны, и perl должен угадывать ваши намерения. Это не всегда правильно. – tobyink

+1

Здесь нет двусмысленности или угадывания здесь. Более конкретный синтаксис ('sort SUBNAME LIST') имеет приоритет над менее конкретным синтаксисом (' sort LIST'). – ikegami

Смежные вопросы