> "Don't be bothered with by the fact that the solutions end with "or false" here. It's a function of how the search algorithms work; the solver looked for more solutions, then failed. I'll admit, I don't totally understand why it only sometimes does this, but it's expected."

I think this is explained in The Power of Prolog[1] that the answers coming from Prolog are not printing text to a terminal, they are valid Prolog terms(/data/code). That's why the result uses the same `;` for OR as code does. Answer (x ; y ; false) is "query can be answered by x or y or no other answer found". (This would let you do meta-programming, reasoning about the results and rewriting the results in a LISPy data-as-code way, if you were more advanced than I am).

Prolog systems do optimisations to jump to the correct answer without searching, if they can, (e.g. database style indexing on the facts and rules) and in those cases there is no code left to search after showing the first answer, no need to prompt the user "should I search for more answers in the remaining code?", and so no need for an output "false" to say "I finished searching and found no more solutions".

[1] https://www.metalevel.at/prolog

This embodies why I don't like Prolog. Prolog's philosophy is that you should just write the predicates without thinking about how the engine works. But as soon as you do something actually complicated, you realize that the different optimization modes of the engine give different results, and shortly after that you'll find yourself in the "exhaustively try every possible combination until we get one that satisfies the predicates" mode, and your code will go from taking 1 second to run to taking 8 days.

And because you don't control the engine (you're not supposed to think about it, after all), there's nothing you can do but rewrite the whole thing in a traditional programming language.

> as soon as you do something actually complicated, you realize that the different optimization modes of the engine give different results

The same is true of SQL query planners. You can perform basic queries without understanding how your SQL engine of choice works under the hood, but if you want performance, you must understand how your DB works. SQL is just the interface.

This is different in kind from imperative programming languages (which are much closer in abstraction to the underlying machine architecture), but we rub along with SQL ok; why not Prolog?

Yeah, but the difference is that SQL provides a huge number of ways to solve the "My query got slow when it got complicated" problem. In Prolog, you have the cut operator, and when that stops working for your usecase, you're just SOL.

I somewhat disagree that you shouldn't be aware of how the engine works. The mechanics are quite simple. Prolog's horn clauses are combined in depth first search manner trying to proof that the negated goal is false.

However, most prolog books focus on rooting the declarative mindset because programmers are generally more familiar with imperative programming. But just as with SQL or lisp there are definitely good ways, bad ways and plain mistakes you can make when approaching a problem.

How is this different from other programming languages though?

One example I often think about is from Ken Silverman: "sub eax, 128" → "add eax, -128". So equivalent ways to write the same program may have different performance characteristics also depending on the tools that are applied. How many people could tell without trying which way to write this example is preferable?

The same phenomenon will be encountered in all kinds of languages, where engine and compiler improvements make existing code faster or slower.

In other languages, you can find the lines where the performance problems are and fix them without breaking the abstraction everywhere else.

I think this is very well phrased, and I would argue the same holds for Prolog too.

In my opinion, a key difference between Prolog and other languages in that regard is one of degree, not kind: Compared to other languages, addressing performance problems in Prolog engines tends to have far greater effects on Prolog programs, because so much is implicit (i.e., left to the engine).

If the performance problem is not in the engine, but in the program itself, then we will face the same questions with Prolog as with other languages: How to formulate the program better, is there a better approach altogether?

For example, earlier today an interesting question regarding performance was posted in the Scryer discussions:

https://github.com/mthom/scryer-prolog/discussions/3341

The comparison in this case is between Gecode and Scryer on a seemingly simple but nontrivial combinatorial task. What is the problem here? Most likely the Scryer engine itself can be improved. And also very likely, there are better ways to model the task, and also better search strategies, and these tend to have far greater performance impact than the base language, and these questions remain also if we change the base language.

In my opinion, these questions regarding different kinds of formulations tend to be more frequently associated with Prolog than with other languages because Prolog is more frequently used for complex tasks where it is not a priori clear how to even approach the problem.

> Prolog's philosophy is that you should just write the predicates without thinking about how the engine works.

This is the definition of declarative programming[0].

0 - https://en.wikipedia.org/wiki/Declarative_programming