Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^2: Small examples of string eval

by brian_d_foy (Abbot)
on May 14, 2006 at 17:06 UTC ( #549339=note: print w/ replies, xml ) Need Help??


in reply to Re: Small examples of string eval
in thread Small examples of string eval

You don't need a eval to do this, and it's easier to do without it. You basically want a higher order function that composes other functions, and all of the functions are going to get the same arguments.

Starting from the finished product, you might have a sort subroutine like this, where the return value is the first thing that returns true (which should be -1 or 1).

sub sortsub { $a cmp $b || other_function( $a, $b ) || ... }

That's the same as writing it as a collection of subroutines that get arguments instead of using globals though:

sub sortsub { string_compare( $a, $b ) || other_function( $a, $b ) || ... }

But I can rewrite that sortsub to take a list of subroutine references as its arguments. Now my sortsub goes through each subroutine and returns when it finds one that returns a true value. If it finds 0 (meaning that sub thought the elements were equal), it goes onto the next subroutine.

sub sortsub { my @subs = @_; foreach my $sub ( @subs ) { my $result = $sub->($a, $b); return $result if $result; } }

I can't use this in sort yet because I can't pass it arguments. I can, however, modify it to return a subroutine reference I can use:

sub make_sort_sub { my @subs = @_; return sub { foreach my $sub ( @subs ) { my $result = $sub->($a, $b); return $result if $result; } }; }

Now, I basically make the reference then use it in my sort block.

my $sort_sub = make_sort_sub( @sub_references ); my @sorted = sort { $sort_sub->() } @stuff;

And here's a full demo, using it with numbers, then strings, then a user-defined sort subroutine. I don't need an eval for any of it.

#!/usr/bin/perl # pre-defined common sort subroutines my %Subs = ( numeric_descending => sub { $b <=> $a }, numeric_ascending => sub { $a <=> $b }, string_descending => sub { $b cmp $a }, string_ascending => sub { $b cmp $a }, case_insensitive => sub { "\L$a" cmp "\L$b" }, ); sub make_sort_sub { my @subs = @_; return sub { foreach my $sub ( @subs ) { my $result = $sub->($a, $b); return $result if $result; } }; } # numbers { my @use_these_subs = map { $Subs{$_} } qw(numeric_descending); my $sort_sub = make_sort_sub( @use_these_subs ); my @sorted = sort { $sort_sub->() } qw( 1 10 11 100 2 12 21 3 31 300 4 5 6 66 7 + 71 ); print "@sorted\n"; } # strings { my @use_these_subs = map { $Subs{$_} } qw(case_insensitive string_asce +nding); my $sort_sub = make_sort_sub( @use_these_subs ); my @sorted = sort { $sort_sub->() } qw( Fred fred FReD Barney barney Betty BETT +Y ); print "@sorted\n"; } # strings by length with user defined subroutine { my @use_these_subs = ( sub { length $a <=> length $b } ); push @use_these_subs, map { $Subs{$_} } qw(string_ascending); my $sort_sub = make_sort_sub( @use_these_subs ); my @sorted = sort { $sort_sub->() } qw( Fred fred FReD Barney barney Betty BETT +Y ); print "@sorted\n"; }
--
brian d foy <brian@stonehenge.com>
Subscribe to The Perl Review


Comment on Re^2: Small examples of string eval
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://549339]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2015-07-08 03:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (94 votes), past polls