If you ignore the funky syntax and the bad performance, Perl (in particular, perl 5) actually makes a decent functional language. It has: As Philippe Verdret put it, ``Perl est un esprit LISP dans un corps C''. (Quoted by Tom Christiansen in ``FMTEYEWTK about Sorting.)

I present here a bit of (actually useful) perl code (without much documentation, of course).

#! /usr/local/bin/perl -w

# Call as:  mpid string1 string2 ... /regexp1/ /regexp2/ ...
# Prints the PIDs of all processes whose `comm' contains one of the 
# strings, or matches one of the regexps.  As such, it is a more
# flexible version of pidof.
#
# Assumes a Unix system with SysV-style ps(1), supporting the -o
# argument and the `comm' field.  Tested on Linux (procps 2.0.0) and 
# Solaris 7.

use strict;

# Call as:  any { predicate } @list
# Returns true if the predicate returns true for any element of the list.
# The predicate is called as a function of one argument---this is different
# from the norm for perl operators, where the predicate would be called with
# $_ bound to the list element.  Note that modifying $_[0] in the predicate
# code will modify the elements of the list.
sub any(&@) {
        my $pred = shift;
        foreach my $x (@_) {
                my $y = $pred->($x);
                return $y if $y;
        }
        return 0;
}

# If passed a string of the form "/regexp/", returns the same string
# with the // removed.  If passed a string of any other form, returns
# the string with regexp metacharacters quoted.
sub refix($) {
        local $_ = shift;
        return $1 if m,^/(.*)/$,;
        return quotemeta($_);
}

open(F,"ps -e -o pid,comm|");

print join " ",
 map { $_->[0] }
  grep { any { my $x=refix shift; $_->[1] =~ /$x/ } @ARGV }
   grep { defined $_->[0] and defined $_->[1] }
    map { [/^\s*(0-9+)\s+(.*)/] }
     map { (/(.*)\n$/)[0] }
      <F>;
print "\n";
close F;
__END__
The core of the program is the long sequence of greps and maps, which is most definitely functional in style.

One irritating problem with using Perl functionally is that $_ is always dynamically scoped---and things like grep and map use it, rather than simply taking a function of one argument as they (or their counterparts) do in most languages. For example, if you were to modify any above to use map, it would interfere with the use of `$_->[1]' in the first grep. The best way to deal with this is to write your own versions of map, grep, etc. Well, that's the second-best way. The best is to use another freaking language. But I digress.

Another problem---even worse, perhaps---is the lack of formal parameters, and the specialness of @_, but that is a rant for another day.

See also: Schwartzian transform.

Log in or register to write something here or to contact authors.