Archive for the 'Perl' Category

Larry’s Filename Fixer for Windows

Reading Raymond’s post about bulk file renaming reminded me of Larry Wall’s filename fixer. This is a great thing to have in your toolbox. Here’s a minor tweak that allows it to work in Windows CMD.exe.

I call this renamer.cmd to avoid conflict with CMD’s much-less-useful built-in rename.


@rem = '
@echo off
perl -w %~f0 %*
exit /B %ERRORLEVEL%
';

# rename - Larry's filename fixer
$op = shift or die "Usage: renamer expr [files]\n";
chomp(@ARGV = <STDIN>) unless @ARGV;

# cmd.exe doesn't do glob expansion
@ARGV = map glob, @ARGV;

for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

Update:
Oops! Who woulda thunk that the first Google hit for “Larry’s filename fixer” would be a book warez site? Link changed to point at Google’s Usenet archive.

Advertisements

Larry Wall on Perl 6

Larry Wall gave a keynote entitled Present Continuous, Future Perfect at OSDC 2006. It was back in February, but I didn’t discover the audio and slides until tonight.

The deck is 150+ slides, and covers the upcoming features in Perl 6. There’s a Wiki page for the talk here, which includes a full text transcript.

The Upshot of Ugly Syntax

I just realized that one of the reasons I choose Perl for “quick hacks” is because the syntax is so ugly and inconsistent.

It’s a psychological thing. If I were to select Ruby, for example, I’d feel a tremendous obligation to write a beautiful well-designed program. I’d probably create a subversion repository, create unit tests, automate, etc. These are all important things, but I want to amortize their up front cost over the term of a long project.

I choose Perl because it takes the pressure off.

Memoize.pm

Wow, Perl’s Memoize.pm is cool. Try this:


   use Memoize;
   sub fib {
      my $n = shift;
      print "called fib($n)\\n";
      return $n if $n < 2;
      fib($n-1) + fib($n-2);
   }
   print fib(5) . "\\n\\n";
   memoize( 'fib' );
   print fib(5) . "\\n\\n";

It does two different things:

  1. It wraps the function with a caching version.
  2. It replaces all calls to the function with calls to the memoized version. This includes the recursive calls inside the function itself.

It does all of this without requiring any source-level changes to the memoized function. This makes it easy to accelerate any referrentially-transparent function. Just don’t do something dumb like memoize print() or time().

With C++ I can mimic #1, but not #2. It’s a shame, because #2 is the cool part. With my C++ implementation, I only speed up identical repeated calls:


   fib(5);  // slow: makes 14, mostly-redundant, recursive calls
   fib(5);  // fast: purely a look up
   fib(4);  // slow
   fib(6);  // slow

Perl does much better:


   fib(5);  # fast: makes 5 recursive calls
   fib(5);  # fast: purely a look up
   fib(4);  # fast: purely a look up
   fib(6);  # fast: picks up where fib(5) left off

I’m somewhat bugged that I couldn’t duplicate this behavior with C++. Perl needn’t reach into it’s “dynamic language” bag of tricks to achieve this. It just provides access to the symbol table:


   sub a() { print "a\\n"; }
   sub b() { print "b\\n"; }
   *a = \\&b;
   a();     # prints b