Что такое "$ a" и "$ b" в функции "sort()" в Perl?

Я понимаю, как получить результаты, которые я хочу использовать с помощью функции Perl sort(), это больше вопрос о внутренней работе sort().

Откуда берутся переменные "$ a" и "$ b"? Я прочитал документацию для сортировки, и это кажется неясным. Что такое "$ a" и "$ b" и что делает их особенными?

Пример:

my @sorted_list = sort {$a cmp $b} @unsorted_list;

Как сортировать знать, что делать с "$ a" и "$ b", и почему вы не получаете ошибку "Глобальный символ требует явного имени пакета" для "$ a" или "$ b"?

Ответ 1

$a и $b являются свободными глобальными переменными; они освобождаются от того, что Perl позволяет использовать их (в любом месте) без объявления. Они задаются функцией сортировки. Использование любого другого не объявленного глобального типа (в строгом режиме) вызовет ошибку.

Функция сортировки принимает различные формы ввода, один из которых является блоком кода, который является формой, к которой вы обращаетесь.

{$a cmp $b} является блоком кода, он анализируется и передается как "кусок кода" функции сортировки, а Perl проверяет аргументы для сортировки, и если он получает блок кода, sort будет устанавливать $a и $b, если они существуют как глобальные пакеты в кодовом блоке и назначают каждую пару элементов, отсортированных по $a и $b. Все, что вам нужно сделать, это обратиться к ним для управления алгоритмом сортировки. В противном случае используется внутренний алгоритм (который я считаю сортировкой слияния).

http://perldoc.perl.org/functions/sort.html

$a и $b не являются лексическими, они являются глобальными пакетами (или просто глобальными).

В основном вы можете написать:

sort {$main::a cmp $main::b} @list;

Или в другом пакете вы можете написать:

package foo;

sort {$foo::a cmp $foo::b} @list;

На самом деле вы не должны префикс; Я демонстрирую, что $a и $b на самом деле являются глобальными в вашем текущем пакете, а не некоторой магией $a внутри функции сортировки, хотя Perl знает, что позволяет вам определять их даже в строгом режиме.

Вы не можете просто использовать любые переменные (в строгом режиме). Попробуйте:

sort {$A cmp $B} @list;

Global symbol "$A" requires explicit package name at sort.pl

Вы не можете использовать лексический (my $a) в области сортировки.

my $a;
sort {$a cmp $b} @list;

Can't use "my $a" in sort comparison at sort.pl line 13.

$a и $b являются специальными в Perl. Они освобождаются от строгого режима, который не имеет отношения к сортировке, хотя sort был причиной освобождения.

Ответ 2

Что такое "$ a" и "$ b" в [код сравнения] Perl "sort()" функция?

Два значения из списка значений для сортировки. Блок должен возвращать информацию о том, как в конечный результат нужно позиционировать другое.

Что такое "$ a" и "$ b" и что делает их особенными?

Переменные пакета, и нет ничего особенного в них, кроме того, что use strict 'vars'; не считает их ошибкой.

Откуда берутся переменные "$ a" и "$ b" ?

Они заполнены sort.

Как сортировать знать, что делать с "$ a" и "$ b"

Он ничего не делает с ними, кроме как заполняет их, как требуется для выполнения своей функции.

почему бы вам не получить ошибку "Глобальный символ требует явного имени пакета" для "$ a" или "$ b" ?

Это затруднит их использование!

Что произойдет, если вы определяете локальную переменную my $a или my $b, а затем попытаетесь использовать sort в пределах области видимости, где эти [лексические] переменные видны?

Если функция сравнения находится в области my $a и/или my $b, она будет использовать эти переменные вместо переменных пакета sort.

Perl понимает, что вам может быть легко ошибиться, поэтому он проверяет его.

$ perl -c -e'sort { my ($a,$b); $a cmp $b } @a;'
Can't use "my $a" in sort comparison at -e line 1.

Ответ 3

Другие ответы хорошие, поэтому я не буду повторять, но на одну часть вашего вопроса не ответил.

Откуда берутся переменные "$ a" и "$ b"?

Как писал codenheim, sort в основном касается вашего модуля (будь то явный модуль или модуль main) и определения переменных в вашей области. Как? Просто временно отключив strict refs и указав полное имя переменной. При этом переменная может быть доступна через ${$variable_name}.

my $pkgname = caller();
my $varname = "${pkgname}::a";
no strict 'refs';
${$varname} = value;

Примечание. Я обнаружил эту технику в source для Список:: Util.