This seems like a kind of selection bias to me. For the most part we only build "high level" things on top of "low level" things when we're successful in finding a use for them, by definition. The more successful you are, the easier success seems. Put another way, if they weren't "easy" then there wouldn't be a "high level" above them to make the concept of "low level" meaningful or concrete.
Also, as a caution against asserting low level means "easy", I will take this opportunity to drop one of Murphy's Laws:
"An easily understood, workable falsehood is more useful than a complex, incomprehensible truth."
sometimes written as
"All abstractions are wrong, some abstractions are useful."
As an example of a low level abstraction that is both useful and wrong, consider the libc strtod() function, which converts a decimal string to a native floating point representation. If I were to give you the pre-parsed integer significand and integer exponent, base 10, then you'll find there's no mechanism in the C standard library to convert those two integers to the correct double value, despite strtod() having to do the very same thing, at some point after the parsing stage. If all you ever want to do are string to double conversions then this function will always have appeared quite low level, but the reality is that this is only the case because it's always been so damned useful.
Low level things are intrinsically useful and the more useful something is the less wrong it seems.
> Put another way, if they weren't "easy" then there wouldn't be a "high level" above them to make the concept of "low level" meaningful or concrete.
Yeah, the higher level is things that are also rejected at large by the industry and moribond in research like DSL, code generation, modelisation, algebra stuff and proved programs. Things that exists more or less at every level but widespread in CPU making.
Also, as a caution against asserting low level means "easy", I will take this opportunity to drop one of Murphy's Laws:
sometimes written as As an example of a low level abstraction that is both useful and wrong, consider the libc strtod() function, which converts a decimal string to a native floating point representation. If I were to give you the pre-parsed integer significand and integer exponent, base 10, then you'll find there's no mechanism in the C standard library to convert those two integers to the correct double value, despite strtod() having to do the very same thing, at some point after the parsing stage. If all you ever want to do are string to double conversions then this function will always have appeared quite low level, but the reality is that this is only the case because it's always been so damned useful.Low level things are intrinsically useful and the more useful something is the less wrong it seems.