Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Some sort questions - especially hashes

Reply
Thread Tools

Some sort questions - especially hashes

 
 
Dave Saville
Guest
Posts: n/a
 
      10-10-2013
This started out as one question but in trying to solve my problem I
got side tracked - as you do

In the "Perl Cookbook" page 140 under sorting lists there is the
following code:

@ordered = sort { $a->name cmp $b->name } @employees;

Where has 'name' come from? and what is in @employees such that
$a->name means something? I can't work it backwards as it were to
figure it out.

Now the actual problem.

I have a script that is building an HTML table. The table is built
from a hash. The top level entries of the hash are anonymous arrays
the elements of which are the columns.

At present there is a chunk of duplicated formatting code depending on
which of two columns I sort over. Yesterday the inevitable happened in
that I changed the formatting of one set and forgot to make the same
change in the other. The "curse of the duplicated code"

So it got me wondering if I could code one formatting loop and
dynamically set the sort up or down.

$foo = \&sortup;
$foo = \&sortdown if $bar;

foreach (sort $foo keys ......

But I recall scope problems in the past using suborutines that seem
solved if one used sort { ..... } syntax

At present one of the sorts looks like:

foreach my $url (sort {$$urlsref{$site}{$b}[0] <=>
$$urlsref{$site}{$a}[0] or $a cmp $b} keys %{$$urlsref{$site}} ) #
count descending

TIA
--
Regards
Dave Saville
 
Reply With Quote
 
 
 
 
Rainer Weikusat
Guest
Posts: n/a
 
      10-10-2013
"Dave Saville" <(E-Mail Removed)> writes:

[...]


> I have a script that is building an HTML table. The table is built
> from a hash. The top level entries of the hash are anonymous arrays
> the elements of which are the columns.
>
> At present there is a chunk of duplicated formatting code depending on
> which of two columns I sort over. Yesterday the inevitable happened in
> that I changed the formatting of one set and forgot to make the same
> change in the other. The "curse of the duplicated code"
>
> So it got me wondering if I could code one formatting loop and
> dynamically set the sort up or down.
>
> $foo = \&sortup;
> $foo = \&sortdown if $bar;
>
> foreach (sort $foo keys ......
>
> But I recall scope problems in the past using suborutines that seem
> solved if one used sort { ..... } syntax


----------
sub asc
{
return $a <=> $b;
}

sub desc
{
return $b <=> $a;
}

my @in = map { int(rand(100)); } 0 .. 9;
my $cmp;

$cmp = \&asc;
print($_, "\n") for sort $cmp @in;

print("\n");

$cmp = \&desc;
print($_, "\n") for sort $cmp @in;
-----------

works as it should. What 'scope problems' are you referring to?
 
Reply With Quote
 
 
 
 
Dave Saville
Guest
Posts: n/a
 
      10-10-2013
On Thu, 10 Oct 2013 14:28:13 UTC, Rainer Weikusat
<(E-Mail Removed)> wrote:

> "Dave Saville" <(E-Mail Removed)> writes:
>
> [...]
>
>
> > I have a script that is building an HTML table. The table is built
> > from a hash. The top level entries of the hash are anonymous arrays
> > the elements of which are the columns.
> >
> > At present there is a chunk of duplicated formatting code depending on
> > which of two columns I sort over. Yesterday the inevitable happened in
> > that I changed the formatting of one set and forgot to make the same
> > change in the other. The "curse of the duplicated code"
> >
> > So it got me wondering if I could code one formatting loop and
> > dynamically set the sort up or down.
> >
> > $foo = \&sortup;
> > $foo = \&sortdown if $bar;
> >
> > foreach (sort $foo keys ......
> >
> > But I recall scope problems in the past using suborutines that seem
> > solved if one used sort { ..... } syntax

>
> ----------
> sub asc
> {
> return $a <=> $b;
> }
>
> sub desc
> {
> return $b <=> $a;
> }
>
> my @in = map { int(rand(100)); } 0 .. 9;
> my $cmp;
>
> $cmp = \&asc;
> print($_, "\n") for sort $cmp @in;
>
> print("\n");
>
> $cmp = \&desc;
> print($_, "\n") for sort $cmp @in;
> -----------
>
> works as it should. What 'scope problems' are you referring to?


Thanks.

IIRC I was several depths down in subroutines and using a "sort sub"
syntax to sort and it was similar to this problem with a complicated
deep hash to sort on and it was not sorting correctly until someone on
here pointed out that some part of it was out of scope. It was a long
time ago. But it *may* have been like this:

use .....


foo(..........

exit

sub foo{
.... sort bar .....
}

sub bar {
}

IOW foo and bar are on the same "level" and possibly bar should have
been defined inside foo.

--
Regards
Dave Saville
 
Reply With Quote
 
Dave Saville
Guest
Posts: n/a
 
      10-10-2013
On Thu, 10 Oct 2013 14:03:37 UTC, Henry Law <(E-Mail Removed)>
wrote:

> On 10/10/13 14:44, Dave Saville wrote:
> > @ordered = sort { $a->name cmp $b->name } @employees;
> >
> > Where has 'name' come from? and what is in @employees such that
> > $a->name means something?

>
> From the perldoc: "where the elements to be compared are passed into
> the subroutine as the package global variables $a and $b".
>
> So in that block (within the braces) $a and $b represent the two sides
> of every comparison that the sort will make; conceptually at any rate
> the sort invokes your block, passing $a and $b to it, and makes its sort
> decision on the final value.
>


Yes I understand that part.

> I don't know what @employees consists of either, but whatever it is the
> construct "$element_of_employees->name" must have some value. An array
> of objects which all implement a "name" method would do.
>


Ah, I thought it might be some sneaky way of sorting on hash keys
assuming the array contained refs to hashes.

> It's just a code fragment; its message is that that you can use whatever
> comparison code you like within your block, not just "<=>", "cmp" and so on.
>



--
Regards
Dave Saville
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      10-11-2013
Ben Morrow <(E-Mail Removed)> writes:
> Quoth "Dave Saville" <(E-Mail Removed)>:
>>
>> IIRC I was several depths down in subroutines and using a "sort sub"
>> syntax to sort and it was similar to this problem with a complicated
>> deep hash to sort on and it was not sorting correctly until someone on
>> here pointed out that some part of it was out of scope. It was a long
>> time ago. But it *may* have been like this:

>
> You can get problems if the sort call and the sub you are sorting by are
> in different packages.


Actually, one will get problems in this case as sort uses the
package-variables $a and $b to pass the objects-to-be-compared into the
comparison routine and if that's not in the same package as the sort call,
naively written code will use a different $a and $a (namely, those of
the package the subroutine belongs to). Symbolic references could be
used to work around that (possibly together with no strict 'refs'):

-------
package AlienCompare;

sub desc {
return ${caller().'::b'} <=> ${caller().'::a'};
}

package Orkshire;

my @in = map { int(rand(100)) } 0 .. 9;

print($_, "\n") for sort AlienCompare::desc @in;
--------


[...]

>> IOW foo and bar are on the same "level" and possibly bar should have
>> been defined inside foo.

>
> Named subs should never be defined inside other named subs in Perl. It
> doesn't achieve anything useful


Depending on the situation, it might: PostgreSQL functions written in
Perl end up being compiled into anonymous subroutines. Insofar things
get complicated enough that more than one Perl subroutine is needed, the
additional ones have to be defined inside the/ a anonymous subroutine
created by the database server (it is possible to escape from the
anonymous routine by terminating it with a top-level }, add some 'free
code' and then get back into a different anonymous sub at the end of the
Postgres function definition, as you suggested a while ago, but that's a
trick I'd rather avoid).

> and sometimes has confusing side-effects
> (you will get a 'variable will not stay shared' warning, and the sub
> won't see the lexicals you necessarily expect).


IMHO, the warning itself is such a confusing side effect:

----------
use warnings;

sub soup
{
my @components = qw(carrots leeks celeriac garlic onion);

sub components
{
return @components;
}

sub mash_it
{
@components = 'vegetable mash';
}
}

soup();

print('A soup made of ', join(', ', components()), ".\n");

mash_it();

print('Now, we just have ', components(), ".\n");
-----------

Since the two inner subroutine are created 'statically' at
compile-time, I wouldn't expect them to pick up new incarnations of
@components created at run time but they will continue to share the
initial one.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
On Hashes - How the hashes printing works? Neela megha shyam Chivukula Ruby 4 05-28-2009 10:56 AM
How to make an array of hashes to a single array with all thevalues of these hashes ? kazaam Ruby 12 09-13-2007 01:30 PM
using hashes as keys in hashes Steven Arnold Ruby 3 11-23-2005 03:25 PM
Hash of hashes, of hashes, of arrays of hashes Tim O'Donovan Perl Misc 5 10-28-2005 05:59 AM
Hashes of Hashes via subs Ben Holness Perl 8 10-08-2003 06:57 AM



Advertisments