FunctionalPerl

 view release on metacpan or  search on metacpan

docs/design.md  view on Meta::CPAN

Check the [functional-perl website](http://functional-perl.org/) for
properly formatted versions of these documents.

---

# The design principles used in the functional-perl library

<with_toc>

## General

### Be properly functional first.

As already mentioned in the introduction on the [[howto]] page, the
modules are built using the functional paradigm from the ground up (as
much as makes sense; e.g. iterations in simple functions are often
written as loops instead of tail
recursion<small><sup>1</sup></small>). A sequences API to build
alternative implementations (like iterator based, or optimizing away
intermediate results) might be added in the future.

<small><sup>1</sup> But this is mainly done just because it's
(currently) faster, and since currently Perl does not offer
first-class continuations.  Avoiding loop syntax and using function
calls everwhere makes it possible to suspend and resume execution
arbitrarily in a language like Scheme, without mutation getting in the
way; but this doesn't apply to current Perl 5.</small>

### Try to limit dependencies if sensible.

E.g. avoiding the use of `Sub::Call::Tail`, `Method::Signatures`,
`MooseX::MultiMethods` or `autobox` in the core modules. (Some tests,
[examples](../examples/README.md) and [Htmlgen](../htmlgen/README.md)
use them.) Declaring dependencies in `FunctionalPerl::Dependencies` so
that tests can skip modules with such dependencies.

### Generally provide functionality both as functions and methods.

*NOTE: since this was written, the method call based style has become
 the primary way to provide functionality, and function based access
 is spotty now. TODO: rewrite this section. BTW, providing functions
 would be good but provide generic wrappers (which also work for
 builtin types which can't have methods)--TODO.*

The sequence processing functions use the argument order conventions
from functional programming languages (Scheme, Ocaml, Haskell). The
methods move the sequence argument to the object position.

For example, both

    list_map *inc, list (1,3,4)

and

    list (1,3,4)->map (\&inc)

result in the same choice of algorithm. The shorter method name is
possible thanks to the dispatch on the type of the object. Compare to:

    stream_map *inc, array_to_stream ([1,3,4])

or the corresponding

    array_to_stream ([1,3,4])->map (\&inc)

which shows that there's no need to specify the kind of sequence
when using method syntax.

This actually needed an implementation trick: streams are just
lazily computed linked lists, hence the object on which the `map`
method is being called is just a generic promise. The promise could
return anything upon evaluation, not just a list pair. Thus it can't
be known what `map` implementation to call without evaluating the
promise. After evaluation, it's just a pair, though, at which point
it can't be known whether to call the `list_map` or `stream_map`
implementation. So how it works is that promises have a catch-all



( run in 0.965 second using v1.01-cache-2.11-cpan-71847e10f99 )