Schwartzian Magic

Beatnik on 2003-05-19T12:38:12

I never thought I'd say this but for some reason the Schwartzian Transformation seemed like the only way to solve a problem I was having...

eval qq!
if ("$params{'sort'}" eq "date")
{ use Time::Local; 
  \@messages = 
  map { \$_->[0] } 
  sort { \$a->[1] <=> \$b->[1] } 
  map { my (\$h,\$m,\$d,\$M,\$y) = 
  \$_->messagedate =~ \/^(\\d{1,2})\\\:(\\d{1,2})        
  (\\d{1,2})\\\/(\\d{1,2})\\\/(\\d{4})$\/;
  [\$_,timelocal(0,\$m,\$h,\$d,\$M-1,\$y) ] }
  \@messages; #Schwartzian Magic
} else 
{ \@messages = 
  sort 
  { lc(\$a->$params{'sort'}) cmp 
    lc(\$b->$params{'sort'}) } \@messages; 
  }
!;
warn $@ if $@;
For some reason, I couldn't sort if from the DB but I needed to sort it properly.

Annika and Els, I'm here for you!


Only question

koschei on 2003-05-19T12:43:51

My only question is: why are you using eval "" rather than eval {} ?

Re:Only question

Beatnik on 2003-05-19T13:10:52

Because I need some vars interpolated and some don't. The $params{'sort'} is dynamic.

Re:Only question

broquaint on 2003-05-19T15:39:37

You still don't need the string eval e.g
if ($params{sort} eq "date")
{ use Time::Local;
  @messages =
  map  { $_->[0] }
  sort { $a->[1] <=> $b->[1] }
  map  { my ($h,$m,$d,$M,$y) =
    $_->messagedate =~ /^(\d{1,2})\:(\d{1,2})
    (\d{1,2})\/(\d{1,2})\/(\d{4})/;
    [$_,timelocal(0,$m,$h,$d,$M-1,$y) ] }
  @messages; #Schwartzian Magic
} else
{ @messages =
  sort
  { lc($a->${\$params{sort}}) cmp
    lc($b->${\$params{sort}}) } @messages;
}

Re:Only question

Beatnik on 2003-05-19T18:29:47

@messages contains a number of objects and I need to call a simple getter. I can't (and shouldn't) access those variables explicitly. So I need the name of that parameter (and yes, I do some checking prior to that eval block). And yes, I am using strict... all of it :P

Re:Only question

broquaint on 2003-05-19T23:17:32

I still don't need the need for strict. The only bits that are interpolated are the string comparison, which doesn't need to be interpolated, and the methods calls, which again, can live outside a string eval. Or am I missing something?


Re:Only question

Beatnik on 2003-05-19T23:36:26

IIRC you can't do method calls based on scalar values within strict. Ofcourse, I still suck at perl ;P

Re:Only question

broquaint on 2003-05-20T13:57:18

You surely can
shell> perl -Mstrict -

sub foo { print "i'm in foo\n" }
my $m = "foo";
main->$m;

i'm in foo
This is because we're not violating strict in anyway (not symbolic, not bareword, declared variable).

With your hash you can do some slippery scalar dereferencing (to keep it all syntactically correct) or just assign the value to a simple scalar e.g

shell> perl -Mstrict -

sub foo { print "i'm in foo\n" }

my %h = ( method => "foo" );
my $m = $h{method};

# slippery syntactic shenanigans
main->${\ $h{method} };

# such a simple scalar
main->$m;

i'm in foo
i'm in foo