factor out recursive pattern