### Re^3: short sorts

by Arunbear (Prior)
 on Apr 03, 2012 at 17:49 UTC ( #963285=note: print w/replies, xml ) Need Help??

in reply to Re^2: short sorts

In what way does the random sort not work?

Just for fun, an example of going functional ;)
```#!/usr/bin/perl
use strict;
use Data::Dump qw(dd pp);
use List::Util qw(reduce shuffle);

# the composables
sub Cmp  { my (\$x, \$y) = @_; \$x cmp \$y }
sub Ncmp { my (\$x, \$y) = @_; \$x <=> \$y }
sub Reverse   { map { scalar reverse \$_ } @_ }
sub Length    { map { length \$_ } @_ }
sub Uc        { map { uc \$_ } @_ }
sub Transpose { reverse @_ }
sub Ab        { (\$a, \$b) }

# naive composer using evil
# composes functions f, g, h into sub { f(g(h(@_))) }
sub Compose {
my \$body = reduce { "\$b(\$a)" } '@_', reverse @_;
eval "sub { \$body }" or die \$@;
}

# special case for sort
sub Compose_ab { Compose(@_, 'Ab') }

sub sorter {
my (\$type, \$src) = @_;

# Legend:
# i = case insensitive
# a = ascending
# d = descending
# r = reverse (right to left)
# n = numbers
# l = length of value

my %sorter = (
a   => [qw/Cmp/],
d   => [qw/Cmp Transpose/],
ai  => [qw/Cmp Uc/],
di  => [qw/Cmp Uc Transpose/],
an  => [qw/Ncmp/],
dn  => [qw/Ncmp Transpose/],
al  => [qw/Ncmp Length/],
dl  => [qw/Ncmp Length Transpose/],
ar  => [qw/Cmp Reverse/],
dr  => [qw/Cmp Reverse Transpose/],
air => [qw/Cmp Uc Reverse/],
dir => [qw/Cmp Uc Reverse Transpose/],
);

my @composed;
if (\$type) {
\$type = join '', sort split //, \$type; # normalize
@composed = @{ \$sorter{\$type} }
or die "Unknown option: \$type";
if (\$src) {
push @composed, \$src;
}
}
else {
@composed = @{ (shuffle values %sorter)[0] };
warn 'random criteria: ' . pp @composed;
}
return Compose_ab(@composed);
}

my @unsorted = qw(red lilac yelloW Green cyan blue magenta);
my \$sort_type = shift;
my \$criteria = sorter(\$sort_type);
dd sort \$criteria @unsorted;

my %master_list = (
alpha => { members => 1 },
beta  => { members => 3 },
gamma => { members => 8 },
delta => { members => 5 },
);

# custom source for \$a, \$b
sub Members { map { \$master_list{\$_}{members} } @_ }
\$criteria = sorter(\$sort_type, 'Members');
dd sort \$criteria keys %master_list;

Replies are listed 'Best First'.
Re^4: short sorts
by Lady_Aleena (Curate) on Apr 06, 2012 at 20:43 UTC

Arunbear, you seem to be having some fun with this, though you have really made it explode beyond a simple silly subroutine that I plopped into my Nifty module. (My Nifty module is where I put subroutines that I use, but can't categorize anywhere else.) What you have written looks like it would have to be put in a stand alone module. You have added a lot of complexity that I am having a hard time following. It could be that I am having a hard time seeing past my own dispatch table.

I am not entirely sure what you mean when you say that you are making this functional. It could be that I see "subroutine", "sub", and "function" used almost interchangeably that I am not picking up on the subtle differences between them.

As to why the random sort is not acting as expected, I am not sure I can explain the results I was seeing returned. The best I can do is say that it was getting new sort parameters for each iteration of the list while it was being sorted. I also had trouble keeping numerical sorts out of the mix which of course would throw up all kinds of warnings when non-numbers were being sorted.

I hope that you found the idea useful and are using it. Thank you for taking the time to play with this and show me what else can be done. Really silly sorts like sorting from the second character or third to the last character will wait until later. I was thinking about assigning hex and ord numbers to each character and sort them that way, but I think that would be the same as a straight up \$a cmp \$b.

Have a cookie and a very nice day!

I've been trying to learn Haskell for greater good. It's a functional language, which (among other things) means functions are first class citizens: you can pass them as arguments to other functions, return them from functions, and easily combine them with other functions.

e.g. whereas in Perl you can create a new string with
```\$foo = \$bar . \$ram . \$ewe;
in Haskell you can create a new function with
```f = g . h . i
(assuming all the argument types match up).

That's what the Compose function I wrote does. I thought of doing that after noticing how similar your various sort functions were, and how they could be built by composing/layering basic operations on top of one another.

I'm not suggesting you write your code like that, I wrote it mainly out of curiosity to see what such a functional style would look like in Perl.

If you're really interested in functional style programming in Perl, you should check out Higher Order Perl, by Mark Jason Dominus. The whole book is about applying functional programming techniques and style to Perl. It's a pretty amazing book. It's also available free online. Hard to beat that.

I am very happy that I gave you something with which to experiment. If you think of anything else you want this to do, please let me see! :)

Have a cookie and a very nice day!

Create A New User
Node Status?
node history
Node Type: note [id://963285]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2018-04-21 19:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (81 votes). Check out past polls.

Notices?