this doesn't modify the object -- it returns a new one (because of how pg.Row.update works)

def apply(self,vbase,deltas,utc=None):
    "this doesn't modify the object -- it returns a new one (because of how pg.Row.update works)"
    if vbase!=len(self.increments): raise BadBaseV(vbase,len(self.increments))
    if not all(isinstance(d,diff.Delta) for d in deltas): raise TypeError('not_delta')
    utc=utc or misc.utcnow()
    # note: intentionally *not* checking that utc is monotonic because I don't want clock drift to ruin life
    reduce(apply_splice,deltas,self.generate()) # i.e. if this fails we have a problem
    return VDList(self.increments+[Increment(utc,deltas)])