The Ciao System
ciao-lang.org
ciao-lang.org
It is not a new project (I'm saying this as a good thing), for example the reference paper for the system is from 2012 http://cliplab.org/papers/hermenegildo11:ciao-design-tplp.pd... It is still developed. As others have mentioned, the actual homepage is here https://ciao-lang.org/. This is currently a link to the reference manual (which I'm shocked that people are having such a negative reaction to. Reference manuals are rare and good).
It is also quite neat that ciao has led the charge towards a lot of recent energy in the prolog community to getting WASM builds working via emscripten. https://ciao-lang.org/playground/
One of the most interesting unique features of Ciao prolog is it's assertion language and static analyzer. https://ciao-lang.org/ciao/build/doc/ciao.html/AssrtLang.htm...
Some other prolog systems now available to run on wasm are SWI-prolog (which unscientifically I think has the largest user community of a prolog) https://swi-prolog.discourse.group/t/swi-prolog-in-the-brows... and Trealla https://github.com/guregu/trealla-js. Tau prolog is a javascript native prolog. http://tau-prolog.org/
For more on prolog generally, this is an excellent resource https://www.metalevel.at/prolog
1. This is the reference manual itself.
2. It's not the homepage.
Here's the homepage which has what the people who can't figure out those two things want:
https://ciao-lang.org/ - including code and an interactive prompt.
E.g. consider the introductory example in https://ciao-lang.org/
app([],Ys,Ys).
app([X|Xs],Ys,[X|Zs]) :- app(Xs,Ys,Zs).
A reader coming across this declaration would probably read this mentally as: "Fact 1: The predicate app when applied to the empty list and two unifiable lists evaluates to true. Fact 2: The predicate applied to the list with head X and tail Xs, a list Ys, and a list with head X and tail Zs evaluates to true when Xs, Ys, and Zs evaluate to true".What a mindf**. Compare to the much clearer:
% base case
app( List1, List2, List3 ) :-
List1 = [],
List2 = List3.
% general case
app( List1, List2, List3 ) :-
List1 = [ Head_of_list1 | Tail_of_list1 ],
List3 = [ Head_of_list3 | Tail_of_list3 ],
Head_of_list1 = Head_of_list3,
app( Tail_of_list1, List2, Tail_of_list3 ).
A reader is much more likely to read this in a logical manner: "App is a (recursive) predicate that takes three lists. The base case evaluates to true when the first list is empty, and the other two lists are equal. The general case first tests if List 1 and List 3 have a common head, and then tail-recursively runs the rule again to see if the remainder of List1 and 3 continue having common heads all the way up to the base case, where List 1 has run out of elements.".The latter reading is far more likely to make you click that this two-part predicate concatenates two lists X and Y to Z.
I get it, the top is probably more language-efficient, but it's nothing a good compiler/interpreter couldn't refactor trivially under the hood. It's obscure for no good reason other than 'brevity' / 'mathematical elegance' or whatnot.
I find prolog very intriguing and for sure I will check it out tomorrow!