def pack(*args):
    """Pack arguments of different types into a list.

    The ``pack`` / ``unpack`` pair is used to ensure that even with mixed
    arguments internal the logic always sees a list of arrays.

    :returns:
        a tuple of ``keys, values``. The ``keys`` are an opaque hashable
        object that can be used to unpack the values. ``values`` will be
        a tuple of flattend arguments.
    """
    keys = []
    values = []
    for arg in args:
        if isinstance(arg, tuple):
            keys.append(len(arg))
            values.extend(arg)
        elif isinstance(arg, dict):
            k, v = zip(*arg.items())
            keys.append(tuple(k))
            values.extend(v)
        else:
            keys.append(None)
            values.append(arg)
    return tuple(keys), tuple(values)
