when there's a little edge case that doesn't *quite* fit your abstraction, so you handle it with a little if/else to get things working. but then later a second little edge case pops up that has the same shape as the first and you're like "ohhh now i get it" and a better abstraction—the one you probably should have used in the first place—reveals itself to you
(in other news, i'm off to rewrite big chunks of my toy language compiler's tokenization and compile-time evaluation code)