1. Programming in very concrete/practical terms because you do not know how to think in precise and abstract terms (do not know math)
2. Thinking more precisely and abstractly (more mathematical way)
3. Only do some key important abstractions, and being a bit hand-wawy again in terms of precision. The reason: important real-world problems are usually very complex, and complex problems resist most abstractions, and also being totally precise in all cases is impossible due to the complexity.
All-in-all it is due to increased complexity in my opinion.
Example: 1. Writing some fun geometry related programs 2. learn about geometry more seriously 3. write software based on a multiple hundred thousand line CAD kernel.
Other example: 1. Write fun games on C64 2. Learn about computer graphics in University 3. Contribute to the source code of Unreal Engine with multiple million lines of code with multiple thousand line class declaration header files.
For example in sports you play for fun, then do some coaching to get better, then play for fun using your new skills and so on.
1. Start by writing programs with vectors and maps.
2. Learn all about data structures, algorithms, cache misses, memory efficiency etc
3. And then write programs with vectors and maps.
But the maps this time are absl::flat_hash_map (or another C++ alternative hash map such as Folly F14, etc) instead of std::map (or even std::unordered_map).
1. Start by doing everything in ReaderT Env IO
2. Learn all about mtl (or monad transformers, free monads, freer monads, algebraic effects, whatever)
3. Do everything in ReaderT Env IO
Example, (1) You start programming with the simplest abstractions and in a concrete way. (2) You learn about all the theory and mathy stuff: data structures, algorithms, advanced types, graphs, architecture, etc. Eventually you become very skilled with these, but at a certain point you start to bump up against their limitations. Technical disillusionment and burnout may set in if you are not careful (3) You return to using abstractions and architecture that are as simple as possible (but no simpler), but with a much deeper understanding of what is going on. You can still do very complex stuff, but everything is just part of a toolbox. Also, you find yourself able to create very original work that is elegant in its seeming simplicity.
I've noticed the same thing in other fields: the best approach their work with a certain novice-like (but effective) simplicity that belies what it took for them to get to that point.
The integration phase goes much deeper. The first stage is about learning how to write programs. The second is about writing programs well. The third is to intuitively reason about how to solve problems well using well-written programs; you can still code, but it's no longer where the lifting is.
> 2. Learn about data structures and algorithms and complexity and software organization.
> 3. Write programs that you think are cool. But since you know more, you can write more cool programs.
Hegel :-)
1. Hack programmatic-functionality in a first language
2. Master the intricacies of a first language, understanding all programmatic concepts through the lens of that languages specific implementation-details. Pedantically argue with those familiar with different language implementations, due to a kind of implementation-plurality/ essential-form blindness
3. Learn additional languages, and 'see past' specific implementation details and pitfalls of each; develop a less biased understanding of the essence of any task at hand
Similarly with programming.
1. Write programs that you think are cool
2. Learn about data structures and algorithms and complexity and software organization.
3. Write programs that you think are cool. But since you know more, you can write more cool programs.
If things are working as they should, the end stage of mathematics and programming should be fun, not tedious. The tedious stuff is just a step along the way for you to be able to do more fun stuff.