reimplement using reduce