not every programming language is general purpose and not every specialized art/teaching/cultural PL has to use conventions that make it comfortable for knowledgeable programers to use
“What is this trying to be? Who is it for?” are almost always great questions to ask when you don’t understand a tool.
Inform7 is not a bad programming language, it’s a specialist language for writing text adventure games. Same with Processing, or shaders, or the Cree language I just reposted about.
C, in many ways, is a bad programming language because it’s trying to address the (large) niche of industrial/commercial programming, but is not fit for purpose.
Many things the PLT community considers obviously good are in fact niche-specific. Even memory safety, which literally saves lives, makes it more difficult to engage in important art forms like glitch art and speedrunning, and important counterculture activities like DRM circumvention and exfiltrating no-fly lists.
one of my favorite interviews is this one with joe armstrong (erlang) and simon peyton jones (haskell) about the development of both of their languages and how while they solved similar issues with similar solutions (and some very different ones) they had very different purposes.
i love erlang, the way it's laid out and the core ideals and goals make a ton of sense to me (very surprising ive worked almost exclusively in SRE and infra roles). and if you are looking to build a robust telecom like system, man is it a great fit (side note: Ericsson estimates 40% of mobile traffic uses its systems, and 3rd party estimates say 90% of internet traffic hits something running on erlang).
now, say you want to do a fancy calculation of any complexity? it's not great at that. so they just offloaded the work to NIFs (which were full of issues).
is the language fraught with issues? ABSOLUTELY. i could complain for hours on the issues with BEAM and erlang (some fixed by Elixir, some fixed by NIFs in rust) but there are tons of silly annoyances that make it impractical for most things.
erlang "solved" crashing by making sure crashes stayed localized by never sharing memory.
haskell did it with magic (i assume type systems are just magic) and laziness.
rust does it with memory safety.
go does the bare minimum and expects the user to have the engineering ability of google to solve issues and handle it completely imploding.
and the list goes on.
the important thing to remember is that programming does not happen in a vacuum. it's important to stop supposing the cow is a sphere when making broad value statements.