Btw, I wanted to note that Prolog is indeed very good at any problem that
requires manipulating recursive data structures, like parsing. But that's one
thing that you can do more easily in Prolog than you can in other languages.
It's one of the things it is good for, if you want, not the one thing it is good
for.

For me, what Prolog does best is get all the ceremony of other programming
languages out of my way and let me concentrate on the problem at hand. By
"ceremony" I mean special syntactic constructs. For example, you don't even
declare variables, as such, in Prolog, there's no assignment expressions,
classes and enums and switch statements, there are no for and while loops etc
etc. Prolog instead gives you a very small set of abstract building blocks that
you can use to write any program. It's like programming with Lego bricks, except
you have one kind of brick, a universal Lego brick that you can build anything
you want with.

Which is why it's so good at solving hard problems, because once you're used to
its abstractions and how to combine them, any problem becomes an exercise in
finding the right way to fit the "bricks" together in the right way [1] [2].

That's also why Prolog is hard to learn: imperative languages have ceremonial
constructs (if-then-else, while-do, yield, etc) for a reason. The reason being,
because that makes it easier to write programs. But not easier to _solve
problems_. Not when the problems get hard anyway [3].

So perhaps this is one reason why people say it's not "general purpose"? Because
it's hard to learn, so it's hard to use when you're just trying to write, dunno,
simple list processing programs, but makes things easier when you're trying to
do something inherently difficult, like write a parser? If I think about that, I
could see how Prolog may come across as a language only good for certain kinds
of problem (which is my attempt to interpret "general purpose", though I'd still
be grateful if someone gave me a clear definition that I can grok).

____________

[1] As an example, here's two ways to write the Ackermann–Péter function in
Prolog:

https://rosettacode.org/wiki/Ackermann_function#Prolog

One uses the is/2 predicate, which is an instance of what I mean by "ceremony".
The second uses Peano notation for natural numbers and is basically a direct
translation of the Function's definition on wikipedia (full disclosure: the
second version is mine).

[2] That's also the reason why it's infinitely easier to machine-learn Prolog
programs, as in Inductive Logic Programming, than to learn, say, Python
programs. If you want to loop in Prolog, all you need to do is place a literal
in the body of a clause that has the same symbol as the literal at the head of
the clause: p:- q, p is recursive. So if you want loops, just move your "bricks"
around until they're in the right place, and job done. To machine-learn Python
you have to find a way to compose every single special-purpose expression, and
all the other kinds of loops, and that gets a lot more complicated, more so as a
program grows in size.

It should be noted that you get the same simplicity with languages of the lambda
calculus, hence Inductive Functional Programming is also a thing.

[3] All the high-level abstraction also makes it much harder to read. See the
Peano notation Ackermann-Péter Function above.