Some of the Scryer Prolog features are:
* ISO standard compliant
-* Integrated constraint progamming libraries: clp(B), clp(Z).
-* Definite Clause Grammars
-* Coroutining support (`dif/2`, `freeze/2`, ...)
+* Integrated constraint programming libraries: [clp(B)](/clpb.html), [clp(Z)](/clpz.html).
+* [Definite Clause Grammars](/dcgs.html)
+* Coroutining support ([`dif/2`](/dif.html), [`freeze/2`](/freeze.html), ...)
* Tabling and SLG resolution
* Compact string representation
-* Network libraries (TCP sockets, HTTP server, HTTP client, ...)
-* Cryptographical predicates
+* Network libraries ([TCP sockets](/sockets.html), [HTTP server](/http/http_server.html), [HTTP client](/http/http_open.html), ...)
+* [Cryptographical predicates](/crypto.html)
* WAM based engine, cross-platform made in Rust
* _and more..._
of logic programming. That's because Prolog allows us to elegantly solve many tasks with short and
general programs.
-If you want to learn more about Prolog history, [check this video](https://www.youtube.com/watch?v=74Ig_QKndvE).
+If you want a more detailed description of Prolog, check [A Tour of Prolog](https://www.youtube.com/watch?v=8XUutFBbUrg).
+
+If you want to learn more about Prolog history, [check this video](https://www.youtube.com/watch?v=74Ig_QKndvE) and [this talk](https://prologyear.logicprogramming.org/videos/PrologDay_Session_1_talk.mp4).
## Where can I learn Prolog?
There are a lot of classical Prolog books. Those books can teach you the basics of Prolog. Some
-examples are: _The Art of Prolog (Shapiro)_, _Programming in Prolog (Cloksin, Mellish)_ and _The Craft
+examples are: _The Art of Prolog (Shapiro)_, _Programming in Prolog (Clocksin, Mellish)_ and _The Craft
of Prolog (O'Keefe)_. However, most of them are not updated to _modern_ Prolog.
We recommend _[The Power of Prolog (Markus Triska)](https://www.metalevel.at/prolog)_ for modern Prolog. For reference about
the builtin Prolog modules and libraries in Scryer, check the documentation site. It's this!
+/** Arithmetic predicates
+
+These predicates are additions to standard the arithmetic functions provided by `is/2`.
+*/
+
:- module(arithmetic, [expmod/4, lcm/3, lsb/2, msb/2, number_to_rational/2,
number_to_rational/3, popcount/2,
rational_numerator_denominator/3]).
:- use_module(library(error)).
:- use_module(library(lists), [append/3, member/2]).
+
+%% expmod(+Base, +Expo, +Mod, -R).
+%
+% Modular exponentiation. Base, Expo and Mod must be integers.
expmod(Base, Expo, Mod, R) :-
( member(N, [Base, Expo, Mod]), var(N) -> instantiation_error(expmod/4)
; member(N, [Base, Expo, Mod]), \+ integer(N) ->
X is abs(B) // gcd(A,B) * abs(A)
).
+%% lsb(+X, -N).
+%
+% True iff N is the least significat bit of integer X
lsb(X, N) :-
builtins:must_be_number(X, lsb/2),
( \+ integer(X) -> type_error(integer, X, lsb/2)
msb_(X1, -1, N)
).
+%% msb(+X, -N).
+%
+% True iff N is the most significant bit of integer X
msb(X, N) :-
builtins:must_be_number(X, msb/2),
( \+ integer(X) -> type_error(integer, X, msb/2)
M1 is M + 1,
msb_(X1, M1, N).
+%% number_to_rational(+Real, -Fraction).
+%
+% True iff given a number Real, Fraction is the same number represented as a fraction.
number_to_rational(Real, Fraction) :-
( var(Real) -> instantiation_error(number_to_rational/2)
; integer(Real) -> Fraction is Real rdiv 1
A is A0 // G,
B is B0 // G.
+%% rational_numerator_denominator(+Fraction, -Numerator, -Denominator).
+%
+% True iff given a fraction Fraction, Numerator is the numerator of that fraction
+% and Denominator the denominator.
rational_numerator_denominator(R, N, D) :-
write_term_to_chars(R, [], Cs),
append(Ns, [' ', r, d, i, v, ' '|Ds], Cs),
number_chars(N, Ns),
number_chars(D, Ds).
+%% popcount(+Number, -Bits1).
+%
+% True iff given an integer Number, Bits1 is the amount of 1 bits the binary representation
+% of that number has.
popcount(X, N) :-
must_be(integer, X),
'$popcount'(X, N).