In that case I won't try to correct any of the author's misconceptions, but I'll advise anyone reading the article to not take anything the author says seriously because they are seriously confused and have no idea what they're talking about.
Sorry to be harsh, but it seems to me the author is trying their damnedest best to misunderstand everything ever written about Prolog, and to instead apply entirely the wrong abstractions to it. I don't want to go into the weeds, since the author doesn't seem ready to appreciate that, but Prolog isn't Python, or Java, or even Picat, and to say e.g. that Prolog predicates "return true or false" is a strong hint that the author failed to read any of the many textbooks on Prolog programming, because they all make sure to drill into you the fact that Prolog predicates don't "return" anything because they're not functions. And btw, Prolog does have functions, but like I say, not going into the weeds.
Just stay away. Very misinformed article.
IMO it would be better to have something like Prolog as part of a "better designed" language per se. I can't come up with a good proposal myself - language design is hard, including syntax design - but imagine if Prolog would be a part of python. That feature would then be used by more people. (This is just an example; just randomly creeping in features into a more successful language, also often won't work. I am just giving this as an example that MIGHT be better.)
Count yourself lucky you (probably) learned programming in a language like Java or Python, and not, say, FORTRAN. Because then you'd really pray for the simplicity and elegance of definite clauses.
(Or not. FORTRAN programmers can write FORTRAN in any language, even FORTRAN).
You can't do length + 1 as a single expression in any language though, in python for example len(ls) + 1 is two expressions, but I get what you mean, it is a little less terse. But those commas in prolog are super useful. And you can make your example bidirectional too:
``` :- use_module(library(clpfd)).
foo(List, X) :- length(List, Out), X #= Out + 1. ```
``` ?- foo(X, 3). X = [_, _] .
?- foo(X, 3), X = [a,b]. X = [a, b] . ```
-----
No standarized collection types:
I think that's a feature rather than a bug. The ability to just use infix and compound terms in a generic way without it being tied to a clause or operator is a huge feature. For example:
``` pets(dog-rex-poodle, dog-fluffy-bishon). ```
That defines the collection in a semantic or mathematical sort of way, then you can pass that into whatever data structure you want, whether it's a ordered map or a hashmap or whatever.
----
No boolean values:
That's also a feature in prolog, same as having no null. It's the same sort of motivation for Haskell's Maybe and Either types or Rust's Option and Result types, same kind of usefulness.
----
Cuts are confusing:
Conditionals don't need to use cuts, the modern prolog way of doing it is using the reif library:
``` :- use_module(library(reif)).
if_(Cond, Then, Else) ```
For example:
``` :- use_module(library(clpfd)). :- use_module(library(reif)).
sign(X, S) :- if_(X #> 0, S = pos, S = nonpos). ```
---
Non-cuts are confusing:
This isn't doing what you're thinking:
``` \+ (A = B) ```
It's unifying A with B, `A = B` unifies. You want `dif(A, B)`.
----
Straying outside of default queries is confusing:
It might be tempting to use bagof, but it's not monotonic. You should try to write as much prolog code as you can in a pure, monotonic way, so your code can take advantage of prolog's unique advantages, like monotonic debugging.
Check out the SWI prolog discourse group, there's a lot of good stuff in there and everyone's very supportive to newbies. And Markus Triska's website and youtube channel Power of Prolog is a super useful resource for all this stuff, a good place to go if you want to know what sets prolog apart. A lot of prolog's usefulness doesn't show up as an embedded language either, like minikanren isn't "pretty much prolog", it lacks a lot of stuff that prolog offers. Multiparadigm programming languages are also really popular now, but a lot of what sets programming languages apart isn't what they can do, it's what they can't do, what sort of paradigm or way of thinking they force you to adopt.
x = length(list) + 1
On the other hand I don’t really see why it is an issue with Prolog (maybe there are more complicated situations than the example)
The thing to keep in mind is that Prolog borrows its syntax and semantics from (a fragment of) First Order Logic, and that's where its treatment of functions comes from. In FOL there's a concept of a "term": a variable is a term, a constant is a term, and a function symbol followed by one or more comma-separated terms in parentheses is a term. So if f is a function symbol, f(X,a(b), c) is a term, where X is a variable (in Prolog notation where variables start with capital letters or _). Terms are mapped to functions over objects in the domain of discourse by a pre-interpretation (long story). Terms are arguments to atomic formulae which look exactly like terms with one or more arguments, except they have predicate symbols rather than function symbols, so if p is a predicate symbol, then p(f(X,a(b), c), d, 1, 2, 3) is an atomic formula, or atom.
There's a bit of terminological confusion here because Prolog calls everything a "term", including atomic formulae, and it calls its constants "atoms", but, well, you learn to deal with it.
The difference between terms (in both Prolog and FOL) and functions (in most programming languages) is that terms are not evaluated and they are not replaced by their values. Rather, during execution of a Prolog program, variables in a term are bound to values, by unification, and when execution is over, if you've got all your ducks in a row, all variables in your program should be bound to some term with no variables, and all terms be "ground" (i.e. have no variables).
That's because a ground term is essentially a proposition, and so it has a truth value of true or false. The point of FOL and of Prolog, and every other logic programming language is to carry out a proof of a theorem, expressed as a logic program. If a term has variables we can't know its truth value because it may correspond to a different value of a function, depending on the values of its variables. So to know the truth or falsehood of a term we need to ground it. Unification in Prolog is a dirty hack that allows the proof to proceed without fully grounding terms, until the truth of an entire theorem is known, at which point everything becomes ground (or should be ... more or less, it depends).
ASP (Answer Set Programming) instead starts by grounding every term. Then, it basically treats a logic program as a SAT formula and uses a SAT-solver to find its truth or falsehood (it does more than that: it gives you all models of the theorem, i.e. every set of ground atoms that makes it true).
And that's where the tiger got its stripes. Don't expect Prolog (or ASP for that matter) to work like other languages, it has its own semantics. You don't have to like them, but there's a reason why everything is the way it is.