Some sort questions - especially hashes

Discussion in 'Perl Misc' started by Dave Saville, Oct 10, 2013.

  1. Dave Saville

    Dave Saville Guest

    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
    Dave Saville, Oct 10, 2013
    #1
    1. Advertising

  2. "Dave Saville" <> 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?
    Rainer Weikusat, Oct 10, 2013
    #2
    1. Advertising

  3. Dave Saville

    Dave Saville Guest

    On Thu, 10 Oct 2013 14:28:13 UTC, Rainer Weikusat
    <> wrote:

    > "Dave Saville" <> 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
    Dave Saville, Oct 10, 2013
    #3
  4. Dave Saville

    Dave Saville Guest

    On Thu, 10 Oct 2013 14:03:37 UTC, Henry Law <>
    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
    Dave Saville, Oct 10, 2013
    #4
  5. Ben Morrow <> writes:
    > Quoth "Dave Saville" <>:
    >>
    >> 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.
    Rainer Weikusat, Oct 11, 2013
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ben Holness

    Hashes of Hashes via subs

    Ben Holness, Oct 5, 2003, in forum: Perl
    Replies:
    8
    Views:
    547
    Ben Holness
    Oct 8, 2003
  2. Steven Arnold

    using hashes as keys in hashes

    Steven Arnold, Nov 23, 2005, in forum: Ruby
    Replies:
    3
    Views:
    155
    Mauricio Fernández
    Nov 23, 2005
  3. kazaam
    Replies:
    12
    Views:
    260
    Matthias Wächter
    Sep 13, 2007
  4. Neela megha shyam Chivukula

    On Hashes - How the hashes printing works?

    Neela megha shyam Chivukula, May 27, 2009, in forum: Ruby
    Replies:
    4
    Views:
    213
    Markus Schirp
    May 28, 2009
  5. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    201
Loading...

Share This Page