An immutable's getattribute calculates lazy values when not yet cached in the object then adds
    them as attributes.

def _imm_getattribute(self, name):
    '''
    An immutable's getattribute calculates lazy values when not yet cached in the object then adds
    them as attributes.
    '''
    if _imm_is_init(self):
        return _imm_init_getattribute(self, name)
    else:
        dd = object.__getattribute__(self, '__dict__')
        if name == '__dict__': return dd
        curval = dd.get(name, dd)
        if curval is not dd: return dd[name]
        values = _imm_value_data(self)
        if name not in values:
            return object.__getattribute__(self, name)
        (args, memfn, _) = values[name]
        value = memfn(*[getattr(self, arg) for arg in args])
        dd[name] = value
        # if this is a const, it may have checks to run
        if name in _imm_const_data(self):
            # #TODO
            # Note that there's a race condition that eventually needs to be handled here:
            # If dd[name] is set then a check fails, there may have been something that read the
            # improper value in the meantime
            try:
                _imm_check(self, [name])
            except:
                del dd[name]
                raise
        # if those pass, then we're fine
        return value