This may seem like a truism, especially after my previous post, but it bears repeating and restating: You can't write good code without first writing bad code.
Right now I'm in the middle of working out how function pointers and other object-related things are encoded in Aki. It's a pretty miserable experience, to be honest about it. Some of the design decisions I made early on that I thought were going to save me trouble are just making a whole new kind of trouble. But there's really no way to know how to get around that stuff in advance, is there?
In another forum I read from time to time, people were talking about how they liked the Rust language's ideas, but not its semantics. They wanted something that had Rust's memory-management concepts but implemented with less burdensome, noisy syntax. Someone else opined that the only way to get there from there may well be to have Rust reach whatever maturity it's headed for with its particular ideas, and then figure out how to boil down something simpler from that. (Je n’ai fait celle-ci plus longue que parce que je n’ai pas eu le loisir de la faire plus courte...)
"You have to write bad code to write good code" is not an excuse for writing bad code, but an explanation for why it is difficult to write good code at all. Sometimes the only way to know how to do something at all is to do it badly first, and then find out how it can be made better. Any implementation at all is going to be more concrete, and thus easier to render better.
I imagine there are some exceedingly talented people who can create a mental model of The Right Thing the first time out. Consider the case of André Bensoussan. Talent like that is rare and to be cherished. But not envied, because that just sets us up for aspiring to an example that may not be ours to have.
Writing bad code is okay as long as that's not what you settle for.