Check the functional-perl website for properly formatted versions of these documents.

Functional programming on Perl

This project aims to make it easier to reduce the number of places in Perl programs where side effects are being used, by providing facilities like data structures to enable it and tutorials and introductions to show good ways to go about it.

Side effects (mutation and input/output), unless they are contained locally (transparent to the user of a subroutine/method/API) are not part of the method/subroutine calling interface but are implicit (hopefully at least documented), and such a call has lingering effects, possibly at a distance. This makes tracking down bugs more difficult, and can hinder the reuse of program parts in newly combined ways. Also, code using side effects means re-running it may not be idempotent (hence produce failures) or be calculating different values, which prevents its use in an interactive way, like from a read-eval print loop or debugger, and makes writing tests more difficult.

<with_toc>

Teaser

This is an example of the kind of code this project aims to make possible:

# Generate functions which construct PXML objects (objects that
# can be serialized to XML) with the names given her as the XML
# tag names:
use PXML::Tags qw(myexample protocol-version records record a b c d);
# The functions are generated in all-uppercase so as to minimize
# the chances for naming conflicts and to let them stand apart.

print RECORD(A("hi"),B("there"))->string; 
# prints: <record><a>hi</a><b>there</b></record>

# Now create a bigger document, with its inner parts built from
# external inputs:
MYEXAMPLE
  (PROTOCOL_VERSION ("0.123"),
   RECORDS
   (csv_file_to_rows($inpath, {eol=> "\n", sep_char=> ";"})
    # skip the header row
    ->rest
    # map rows to XML elements
    ->map(sub {
              my ($a,$b,$c,$d)= @{$_[0]};
              RECORD A($a), B($b), C($c), D($d)
          })))
  # print XML document to disk
  ->xmlfile($outpath);

# Note that the MYEXAMPLE document above is built lazily:
# `csv_file_to_rows` returns a *lazy* list of rows, ->rest causes
# the first CSV row to be read and dropped and returns the
# remainder of the lazy list, ->map returns a new lazy list which
# is passed as argument to RECORDS, which returns a PXML object
# representing a 'records' XML element, that is then passed to
# MYEXAMPLE which returns a PXML object representing a 'myexample'
# XML element. PXML objects come with a xmlfile method which
# serializes the document to a file, and only while it runs, when
# it encounters the embedded lazy lists, it walks those evaluating
# the list items one at a time and dropping each item immediately
# after printing. This means that only one row of the CSV file
# needs to be held in memory at any given point.

See examples/csv_to_xml_short for the complete script, and the examples page for more.

The above example shows the use of functions as a "template system".

Note that the example assumes that steps have been taken so that the CSV file doesn't change until the serialization step has completed, otherwise functional purity is broken; the responsibility to ensure this assumption is left to the programmer (see [[howto#Pure_functions_versus_I/O_and_other_side-effects]] for more details about this).

If you'd like to see a practical step-by-step introduction, read the [[intro]].

Even if you're not interested in lazy evaluation like in the above, this project may help you write parts of programs in a purely functional way, and benefit from the decreased coupling and improved testability and debuggability that this brings.

Status: alpha

This project is in an alpha status because:

There is a lot that still needs to be done, and it depends on the author or other people be able and willing to invest the time.

(An approach to use this project while avoiding breakage due to future changes could be to add the functional-perl Github repository as a Git submodule to the project using it and have it access it via use lib. Tell if you'd like to see stable branches of older versions with fixes.)

Parts

Documentation

It probably makes sense to look through the docs roughly in the given order, but if you can't follow the presentation, skip to the intro, likewise if you're bored skip ahead to the examples and the howto/design documents.

Please ask me or on the [[mailing_list]] if you'd like to meet up in London, Berlin or Switzerland to get an introduction in person.

Dependencies

(Todo: should all of the above be listed in PREREQ_PM in Makefile.PL?)

Installation

From CPAN

Use your preferred CPAN installer, for example: cpan FunctionalPerl

From the Git repository

git clone https://github.com/pflanze/functional-perl.git
cd functional-perl

# to get the latest release, which is $FP_COMMITS_DIFFERENCE behind master:
git checkout -b $FP_VERSION_UNDERSCORES $FP_VERSION

# to verify the same against MitM attacks:
gpg --recv-key 04EDB072
git tag -v $FP_VERSION
# You'll find various pages in search engines with my fingerprint,
# or you may find a trust chain through one of the signatures on my
# older key 1FE692DA, that this one is signed with.

The bundled scripts modify the library load path to find the files locally, thus no installation is necessary. All modules are in the lib/ directory, export PERL5LIB=path/to/functional-perl/lib is all that's needed.

To install, run the usual perl Makefile.PL; make test && make install.

(The repository might be split into producing several separate CPAN packages (or even repositories?) in the future, thus don't rely too much on the installation process continuing to work the way it is right now.)

</with_toc>