CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
"sort foo <>;" not working

 



anotherperlnoob
Novice

May 7, 2015, 2:11 PM

Post #1 of 6 (2696 views)
"sort foo <>;" not working Can't Post

Hi,
There's a code fragment in my Perl book that I thought I would play with, but it's not working.
The code fragment in the book contains the line

Code
my @sorted = sort by_id <>;

which although not explained in the book I presume to mean something like "for each command line argument, assume it is a file, open it, and pass it to the subroutine "by_id"; the sub should then return a scalar value which will be stored in the array @sorted.


I have cobbled together the following program to test it/observe its behaviour/understand it etc.:


Code
#!/usr/bin/perl  
use strict;
use warnings;

my @a = sort foo <>;
sub foo{
print "in foo: \@_: " . (join ' ', @_) . "\n";
return 1;
}


and am calling it on the command line with

Code
J-PC:J >./test5.pl "C:/Users/J/Documents/code/perl/text2.txt"


and text2.txt contains the text


Code
James|007|Spy 
Number 6|6|Ex-spy
Agent 99|99|Spy with unknown name
Napoleon Solo|11|Uncle spy
Unknown|666|Maybe a spy


which gives me the output

Code
in foo: @_: 
in foo: @_:
in foo: @_:
in foo: @_:
in foo: @_:


which is not what I'm expecting. I'm expecting @_ to contain a line of text; foo it seems is being called for each line in the file, but where does that line go to? $_ is uninitialized inside foo but then I would expect that.
What's going on here, what am I missing?
Thanks very much in advance.

Btw the full code fragment from the book is


Code
my @sorted = sort by_id <>; 
sub by_id {
$a =~ /\|(\d+)/;
my $a_id = $1;
$b =~ /\|(\d+)/;
my $b_id = $1;
return $a_id <=> $b_id;
}



shawnhcorey
Enthusiast


May 7, 2015, 2:41 PM

Post #2 of 6 (2693 views)
Re: [anotherperlnoob] "sort foo <>;" not working [In reply to] Can't Post

For reasons of speed, `sort` sets the variables $a and $b to the two values to compare. For numbers, you would use:

Code
my @sorted = sort { $a <=> $b } @list_of_numbers;


See perldoc -f sort for details.

__END__

I love Perl; it's the only language where you can bless your thingy.

Perl documentation is available at perldoc.perl.org. The list of standard modules and pragmatics is available in perlmodlib.

Get Markup Help. Please note the markup tag of "code".


anotherperlnoob
Novice

May 7, 2015, 3:05 PM

Post #3 of 6 (2690 views)
Re: [shawnhcorey] "sort foo <>;" not working [In reply to] Can't Post


In Reply To
For reasons of speed, `sort` sets the variables $a and $b to the two values to compare. For numbers, you would use:

Code
my @sorted = sort { $a <=> $b } @list_of_numbers;


See perldoc -f sort for details.


OK I just modified my code to print $a and $b and I see the lines of text now:


Code
my @a = sort foo <>; 
my $count=0;
sub foo{
$count++;
print "Iteration " . $count . ": \$a=" . $a;
print "Iteration " . $count . ": \$b=" . $b;
return 1;
}


Thanks.


anotherperlnoob
Novice

May 7, 2015, 3:13 PM

Post #4 of 6 (2689 views)
Re: [anotherperlnoob] "sort foo <>;" not working [In reply to] Can't Post

BTW I should add, my fundamental misunderstanding appears to be that I thought the code was operating like this:

step 1. foo uses the <> operator
step 2. the output of step 1 is fed to sort.

That is not the case, because I just tested calling a subroutine with the diamond operator like this:
bar <>
and it doesn't work.
Rather, sort is taking the arguments foo and <>.


BillKSmith
Veteran

May 8, 2015, 5:50 AM

Post #5 of 6 (2603 views)
Re: [anotherperlnoob] "sort foo <>;" not working [In reply to] Can't Post

Here is a complete program that works as expected. (I have replaced the file with the special file DATA so I could show the data in the post.)

Code
use strict; 
use warnings;
my @sorted = sort by_id <DATA>;
print @sorted;

sub by_id {
$a =~ /\|(\d+)/;
my $a_id = $1;
$b =~ /\|(\d+)/;
my $b_id = $1;
return $a_id <=> $b_id;
}
__DATA__
James|007|Spy
Number 6|6|Ex-spy
Agent 99|99|Spy with unknown name
Napoleon Solo|11|Uncle spy
Unknown|666|Maybe a spy


OUTPUT:

Code
Number 6|6|Ex-spy 
James|007|Spy
Napoleon Solo|11|Uncle spy
Agent 99|99|Spy with unknown name
Unknown|666|Maybe a spy


The diamond operator (<>), in array context, reads the entire file into the array. In this case, the entire array is passed to the function 'sort'. Sort calls the function by_id many times. Each call compares one pair of lines. Sort passes the two line to by_id by putting them in the special global variables $a and $b. The function by_id uses regular expressions to extract the id number from each and then compares these numbers with the space-ship operator (<=>). The result of that comparison is returned to sort. The result is that the lines are sorted into the numerical order of the id numbers.
Good Luck,
Bill


anotherperlnoob
Novice

May 8, 2015, 8:08 AM

Post #6 of 6 (2592 views)
Re: [BillKSmith] "sort foo <>;" not working [In reply to] Can't Post

Thanks very much Bill.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives