Lisp is a general purpose programming language, supports any paradigm and the implementation of domain specific extensions. Tool and library support is very good and there is abundance of tutorials, books and people supporting it. Prolog is not a general purpos programming language, but you have to write relations and queries which are then resolved by SLD. You can implement that in Lisp and it runs very fast e.g. on SBCL which has a JIT compiler; I'm not aware of similar performance with Prolog compilers. Just to name a few limitations.
I love Lisps (especially Racket and Clojure) so let me just be clear that I am not going to argue that one is "better" than the other.
> library support is very good
That depends mostly on the implementation. SWI Prolog has a decent number of libraries available. Tau Prolog can interoperate with JavaScript.
> Prolog is not a general purpos programming language
I've made a HN clone in SWI Prolog. You can represent HTML as lists, like you would in many Lisps. In some sense, Prolog can occasionally feel more general purpose because you don't need a separate language (like SQL) for your database.
> but you have to write relations and queries which are then resolved by SLD.
That is true, yet in some sense this is like stating about Scheme that "you have to write functions which are then evaluated". Yep, you have to do that but it doesn't mean the language can't be used for X.
> there is abundance of tutorials, books and people supporting it.
Yup, I dig SICP, The Little Schemer and Rich Hickey's talks. When it comes to Prolog, Markus Triska's presentations are amazing[0].
If it was all about which language has the most books written about it, I'd worry that the "winner" would be Java. (I haven't particularly enjoyed the books I've read about Java though.)
> supports any paradigm
I'm not sure that is necessarily a good thing. JavaScript kinda does this, and I feel like I can never tell if a function or method call is pure or mutates something. Does `foo.sort()` modify `foo` itself, or does it just return an a sorted collection of the elements in `foo`?[1]
I also find it confusing in Common Lisp that `sort` is destructive[2]. I think Clojure fares better there by sticking to immutability.
sort being likewise destructive in TXR Lisp is a bit of a regret of mine; we can easily have a nsort (non-consing sort) be destructive, and sort being equivalent to (nsort (copy obj) ...).
I think that the designers get seduced by the fact that we have such good techniques for in-place sorting that the idea of sorting becomes synonymous with those techniques.
You would never implement a non-destructive sort first and then add an accompanying destructive one; the non-destructive one is the afterthought.
The Javascript blog doesn't really nail things here. It's perfectly legitimate to return "this" and mutate, and possibly useful. For instance, we could have an accumulator object such that:
accumulator(42).add(1).add(1).sub(4)
ends up with 40. Returning the object allows for threading through expressions like this, which works imperatively also.
In the case of Lisp, the destructive sort must return a value that is captured, because if the object is a list, and that list is sorted by a re-arrangement of the cons cells, the original list reference is quite likely longer a reference to the entire list.
Returning a value that the caller must capture also allows the operation to be specified as being destructive or not. If the caller never touches the input object after passing it into the operation, and just uses the returned one, it cannot tell.
Returning a value also allows for a succinct fix for broken code. If the sort was not intended to be destructive in some (f (sort x) y) expression, you just insert (f (sort (copy x)) y) instead of a verbose workaround like (let ((xc (copy x)) (f xc y)).
Likewise in the accumulator case, if we want to avoid mutating some original accumulator, we could have a copy method:
var new_acc = old_acc.copy().add(1).mul(2) // old_acc stays 42, new_acc is 86.
> Prolog can occasionally feel more general purpose
That's subjective; Prolog is/was not intended to be a general purpose programming language, as little as e.g. SQL. And human imagination and perseverance make it possible to reach the goal even under the most adverse circumstances. If you make an effort, you can also build an HN clone in Assembler or Brainf*ck. You cannot conclude from this that the language is intended/suited for this.
> yet in some sense this is like stating about Scheme that "you have to write functions which are then evaluated"
No. There are different ways to evaluate rules. If you don't like SLD then the tinkering begins if you want to stay in Prolog.
> I'm not sure that is necessarily a good thing
It is. E.g. MOP in Lisp is something extremely powerful. With macros you can do things that languages like JavaScript (or Prologue) can only dream of; but you know that yourself for sure.
How is it limiting?