Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly are "$a" and "$b" in Perl's "sort()" function?

I understand how to get the results I want from using Perl's sort() function, this is more a question about the inner workings of sort().

Where do the "$a" and "$b" variables come from? I read through the documentation for sort and it seems unclear. What are "$a" and "$b" and what makes them special?

ex:

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

How does sort know what to do with "$a" and "$b" and why don't you get the "Global symbol requires explicit package name" error for "$a" or "$b"?

like image 212
tjwrona1992 Avatar asked Sep 30 '14 18:09

tjwrona1992


2 Answers

$a and $b are exempt global variables; they are exempt in that Perl allows them to be used (anywhere) without being declared. They are set by the sort function. Use of any other undeclared global in sort (in strict mode) will trigger an error.

The sort function accepts various forms of input, one being a code block, which is the form you are referring to.

{$a cmp $b} is a code block, it is parsed and passed as a "chunk of code" to the sort function, and Perl checks the arguments for sort and if it receives a code block, sort will set $a and $b, if they exist as package globals within the code block, and assign each pair of items being sorted to $a and $b. All you have to do is refer to them to control the sort algorithm. Otherwise, the internal algorithm is used (which I think is merge sort).

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

$a and $b are not lexicals, they are package globals (or just globals).

In a main you can write:

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

Or in another package, you could write:

package foo;

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

You shouldn't actually prefix like this; I am demonstrating that $a and $b are actually globals within your current package, and not some magic $a within the sort function, although Perl knows to allow you to define them even with strict mode.

You can't just use any variables (in strict mode). Try:

sort {$A cmp $B} @list;

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

You cannot use a lexical (my $a) in scope of sort.

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

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

$a and $b are special anywhere in Perl. They are exempt from strict mode, which is unrelated to sort, though sort was the reason for the exemption.

like image 141
codenheim Avatar answered Oct 27 '22 07:10

codenheim


What exactly are “$a” and “$b” in [the compare code of] Perl's “sort()” function?

Two values from the list of values to sort. The block is to return information as to how one should be positioned to the other in the final result.

What are "$a" and "$b" and what makes them special?

Package variables, and there's nothing special about them except that use strict 'vars'; does not consider using them to be an error.

Where do the "$a" and "$b" variables come from?

They are populated by sort.

How does sort know what to do with "$a" and "$b"

It doesn't do anything with them except populate them as required to perform its function.

why don't you get the "Global symbol requires explicit package name" error for "$a" or "$b"?

That would make it rather hard to use them!

What happens if you define a local variable, my $a or my $b, and then try and use sort within a scope where those [lexical] variables are visible?

If your compare function is in scope of a my $a and/or my $b, it will use those variables instead of the package variables sort populates.

Perl realizes you might be an easy mistake to make, so it checks for it.

$ perl -c -e'sort { my ($a,$b); $a cmp $b } @a;'
Can't use "my $a" in sort comparison at -e line 1.
like image 29
ikegami Avatar answered Oct 27 '22 07:10

ikegami