reimplement with iterator