The concept of abstraction is simple and clear when you think about programming as primarily the act of teaching other people (future maintainers, other contributors, and my forgetful self) rather than writing instructions for a computer. An abstraction is simply a grouping of human-level concepts. Good abstractions are generally easy to teach and learn.
Some abstractions are more useful/helpful/powerful than others. The usefulness of an abstraction often depends on the domain. Much of the time, the best way to find out the right abstractions is to first create multiple things with no new abstractions, then decide that everyone will save time if you merge some of the concepts you created. It's good to use well-known, tested abstractions early on, but it's risky to create new abstractions prematurely.
Sometimes a function, data structure, interface, or API happens to embody an abstraction very cleanly. When that works out, the abstraction is easy to teach and tends to be more useful. Most abstractions are a bit messier than that, though, which is why abstraction is really a human-level teaching/learning construct rather than any element of programming languages.
Some abstractions are more useful/helpful/powerful than others. The usefulness of an abstraction often depends on the domain. Much of the time, the best way to find out the right abstractions is to first create multiple things with no new abstractions, then decide that everyone will save time if you merge some of the concepts you created. It's good to use well-known, tested abstractions early on, but it's risky to create new abstractions prematurely.
Sometimes a function, data structure, interface, or API happens to embody an abstraction very cleanly. When that works out, the abstraction is easy to teach and tends to be more useful. Most abstractions are a bit messier than that, though, which is why abstraction is really a human-level teaching/learning construct rather than any element of programming languages.