(fn, t1, t2, normalise)

    Calculates the distance between trees t1 and t2. Can optionally be normalised to range [0, 1].
    If the trees have different leaf sets, the distance is calculated on their intersection. This incurs
    some overhead - if the trees are known to have the same leaves, then the underlying distance function [listed below]
    can be called instead, although in these cases the Tree arguments will need to be replaced with Tree.phylotree
    to make sure the appropriate data structure is passed.
    By default the distance is taken to be zero if the leaf overlap between the trees is less than `min_overlap`. This
    value can be customised using the parameter `overlap_fail_value`.
    E.g.
        treeCl.treedist.eucdist(t1, t2, False) is the leafset checking equivalent of
        treeCl.treedist.getEuclideanDistance(t1.phylotree, t2.phylotree, False)

    Distance functions:
        eucdist
        geodist
        rfdist
        wrfdist

    Underlying non-leafset-checking Distance functions:
        getEuclideanDistance
        getGeodesicDistance
        getRobinsonFouldsDistance
        getWeightedRobinsonFouldsDistance

    :param t1: Tree
    :param t2: Tree
    :param normalise: boolean
    :param min_overlap: int
    :param overlap_fail_value: any
    :return: float

def _generic_distance_calc(fn, t1, t2, normalise, min_overlap=4, overlap_fail_value=0):
    """(fn, t1, t2, normalise)

    Calculates the distance between trees t1 and t2. Can optionally be normalised to range [0, 1].
    If the trees have different leaf sets, the distance is calculated on their intersection. This incurs
    some overhead - if the trees are known to have the same leaves, then the underlying distance function [listed below]
    can be called instead, although in these cases the Tree arguments will need to be replaced with Tree.phylotree
    to make sure the appropriate data structure is passed.
    By default the distance is taken to be zero if the leaf overlap between the trees is less than `min_overlap`. This
    value can be customised using the parameter `overlap_fail_value`.
    E.g.
        treeCl.treedist.eucdist(t1, t2, False) is the leafset checking equivalent of
        treeCl.treedist.getEuclideanDistance(t1.phylotree, t2.phylotree, False)

    Distance functions:
        eucdist
        geodist
        rfdist
        wrfdist

    Underlying non-leafset-checking Distance functions:
        getEuclideanDistance
        getGeodesicDistance
        getRobinsonFouldsDistance
        getWeightedRobinsonFouldsDistance

    :param t1: Tree
    :param t2: Tree
    :param normalise: boolean
    :param min_overlap: int
    :param overlap_fail_value: any
    :return: float
    """
    if t1 ^ t2:
        if len(t1 & t2) < min_overlap:
            return overlap_fail_value
            #raise AttributeError('Can\'t calculate tree distances when tree overlap is less than two leaves')
        else:
            t1, t2 = _equalise_leaf_sets(t1, t2, False)

    return fn(t1.phylotree, t2.phylotree, normalise)