Several package files may be stitched together to form a complete implementation. This is achieved, in a package (including, but not restricted to, the top-level package file), by inclusion statements such as:
use Mpfq::defaults; use Mpfq::defaults::flatdata; our @parents = qw/ Mpfq::defaults Mpfq::defaults::flatdata /;
The question which arises is the decision of what happens if a given code_for_xxx
functions exists in package and also one or several of its parents. We distinguish the notion of a function code_for_xxx
appearing in a given package, where we say the the package directly provides the function, or appearing in a package or one of this ancestor, in which case we say that the function is reachable from that package.
The following rules are applied to constitute the list of functions reachable from a package unambiguously.
If a package directly provides a function, this implementation has precedence over all functions of the same name reachable from any of its parents.
If a package does not provide a given function directly, this function must be reachable by at most one of the package's parents. As a moderating exception to this rule, we also tolerate (albeit at the expense of a warning) the situation where the only implementation of a function which is reachable from a given package is within a single ancestor of the package, but accessible from the package via two distinct ancestry threads.
To alleviate the concern about conflicting ancestries to reach a function from a given package, a conflict resolution mechanism exists. This involves the package variable $resolve_conflicts
. For example, some default package files of MPFQ include a code fragment similar to:
use Mpfq::defaults; use Mpfq::defaults::flatdata; our @parents = qw/ Mpfq::defaults Mpfq::defaults::flatdata /; our $resolve_conflicts = { vec_set => 'Mpfq::defaults::flatdata', vec_ur_set => 'Mpfq::defaults::flatdata', };
The syntax of this hash table should be self-explanatory.