Prolog has many issues; for instance the lack of types and mode declarations, and backtracking almost never being what you want. This was addressed in Mercury [1] but much of the baby was thrown out with the bathwater. (IMHO Mercury ultimately landed closer to the MLs than to Prolog.) The academic literature suggests classic Prolog got fast enough in the late 1980s / early 1990s on stock hardware [2]; see also Peter Van Roy's intriguing book [3] for what happened next.
IMHO it's worth learning about Prolog as a way of looking at the world -- for instance Isabelle and Lambda Prolog are essentially logic programming engines, albeit with more sophisticated terms and unification algorithms.
I agree that the lack of types is a serious deficiency, but surely that can't be the reason Prolog lost steam? I mean... Python?
As for modes, I'm not convinced they are really needed? I do feel they take away a lot of the beauty of Prolog, and a lot of the incentive to think in relations. (Or at least, I fear they do. I haven't actually programmed in Mercury. Would be happy to be proven wrong.)
Ah, but Python has always had types. Just not static types. It still does not really have static types. Static type validation is done by external tools like MyPy. Python itself ignores type declarations at runtime. Still objects of Python have types. You just cannot reason about them at compile time using only pure Python.
I learnt as an undergrad that every sufficiently large program contains a type system (in the loose PL sense of operations requiring arguments of certain sorts) ... now that can be provided by the language or in an ad hoc way by the program itself. (Yes, shades of the CLOS truism.) Python has learnt this lesson (at least I get this impression from reading hacker news) since I stopped using it circa 2015.
As for modes, well! 1. they were needed for at least one Uni of Melbourne person to receive their PhD degree, and less facetiously 2. they are needed for efficient code generation. They can be inferred for this purpose. One use case you may consider is enforcing the correct dataflow in a DCG. Otherwise they are handy for preventing calls to predicates that would not terminate.
I've never programmed in Mercury but it really looks like an ML to me. It was beautifully engineered in the late 1990s and it's a shame it hasn't received more attention. Its FFI influenced the development of Haskell's.
Prolog doesn't have typed variables, but any Prolog term has a type, the set of Prolog terms that unify with itself. In practice, when you write Prolog, your arguments to predicates are always implicitly typed, for example if you write a program that takes as argument a list, you'll write something like this:
Or at least you learn to do that quickly enough. And note that this implicit typing is used both to select clauses in a predicate, and also to index clauses in the Prolog program database by their first term (in which case the first term better be a constant though, not a list). So it's a bit of a bug-repellent, and a bit of an efficiency booster, both. Just like you get with static types.
Right, I have generalized a bit. It doesn't necessarily have to be Prolog, but I'm referring to logic-programming in general.
There is even a new language that allows to embed logic programming inside of "regular" (imperative/functional) programming code. Forgot the name though.
There appears to be a lot of activity around minikanren [1]. Personally I'm so used to having a powerful metalanguage around (lambda calculus plus or minus a bit) that I can't imagine programming in pure Prolog any more. Which is to say this is probably the way to go in practice, if a subproblem can be solved using logic programming.
Minikanren allows you to program in relations. That is, not only unidirectional functions, X->Y, but you can leave out the X and give the Y, getting all X, which would result in that Y. I always found that talk at RacketCon impressive [1].
I mean, of course, minikanren is also implemented somehow, using lambda, but usually one would not want to rebuild the things minikanren offers.
I have not yet tried to use minikanren inside an otherwise "normal" program, but I suspect it will just work.
IMHO it's worth learning about Prolog as a way of looking at the world -- for instance Isabelle and Lambda Prolog are essentially logic programming engines, albeit with more sophisticated terms and unification algorithms.
[1] https://mercurylang.org/
[2] https://www.hpl.hp.com/techreports/Compaq-DEC/PRL-RR-36.pdf
[3] https://www.info.ucl.ac.be/~pvr/book.html