factor out higher order functions to make it simpler to understand