Drummyfish's prolog cheatsheet, released under CC0 1.0.

GENERAL:

  - Use swi-prolog (swipl) or GNU prolog (gprolog).
  - run from CLI like:

      swipl my_program.pl argument1 argument2

  - to run a query from a script, use snippet (will output all solutions):

      run_query( query_to_run ).  % e.g. cat(X)
      :- run_query(Goal),call(Goal),write(Goal),nl,fail;true.
      :- halt.

  - Pure prolog only has HORN CLAUSES. These are disjunctions (or) of literals,
    of which at most one is non-negated. I.e.:

      not(X) or not(Y) or not(Z) or ... [or A]

    Which can be rewritten to conjunction (and) as:

      X and Y and Z and ... => A

    If only non-negated literal is present (A), we call it a FACT. If there is
    no positive literal, we call it a GOAL clause (X and Y and Z ...).

SYNTAX & SEMANTICS:

  - case sensitive
  - Double and single quotes are not the same! (string vs atom, respectively)
  - % line comment
  - /* multi-line comment */
  - Basic syntactic element is a TERM. A term can be either of these:
    - ATOM: general purpose name, e.g.: abc, my_dog, 'my cat'
    - NUMBER: int or float, e.g.: 10, -3, 15.3
    - VARIABLE: names, start with uppercase or underscore, e.g.: X, Item, _item
    - COMPOUND TERM: atom with arguments, e.g. cat(X), dog_owner(me,lassie)
    - LIST: collection of terms in square brackets, e.g.: [cat, dog, horse]
    - STRING: sugar for list of either ints or atoms of length 1, e.g.: "hello"

  - The program is a sequence of CLAUSEs, each of which is of form:

      A :- B.      /* e.g.:      animal(X) :- dog(X).   */
  
    which means B (body) implies A (head), i.e. B => A. We call these RULEs.
  - Clause with an empty body is a FACT (a rule that says head is always true):

      A.           /* e.g.:      dog(lassie).           */

  - Clause with an empty head gets executed immediately:

      :- B.        /* e.g.:      :- halt.               */

  - B (body) consists of PREDICATEs (functions which get called and return a
    bool value). They can be joined with , (and, conjunction) or ; (or,
    disjunction, but this is not a Horn Clause!). We call this a GOAL. E.g.:

      siblings(X,Y) :- parent_of(Z,X), parent_of(Z,Y).
                                  /* goal is: parent_of(Z,X), parent_of(Z,Y) */
      animal(X) :- cat(X);dog(X). /* if X is a cat or a dog, X is an animal  */
  - QUERY is a question (usually run from REPL, to run from script see above)
    whose answer is to be computed. Its result is either bool, e.g.:

      ?- dog(lassie).
      Yes

    or a list of solutions (substitutions of variables such that the query is
    true), e.g.:

      ?- dog(X).
      dog(lassie)
      dog(doge)

    A special single underscore (_) variable can be used, which means
    "any term" (multiple _s in the same query don't mean the same thing as
    other variables).
  - UNIFICATION of two terms mean that they are either the same term, or
    variables in them can be substitued so that they become the same (can be
    tested with = operator).


BUILT-IN PREDICATES:

  A -> B     if-then (implication) often written also with else (C) as:
             A -> B ; C (means (A and B) or (not(A) and C))
  X = Y      unification, true if X and Y unify
  R is E     expression evaluation (arithmetic): true if R is a result (single
             number, NOT an expression) of evaluating expression E, which is
             e.g.: (5 + 4 / 2)
  E1 =:= E2  comparison (equality) of two expressions: true if the results of
             evaluating expressions E1 and E2 equal
  E1 =/= E2  negation of =:=
  E1 < E2    less than, similar to =:=
  E1 > E2    greater than, similar to <
  halt       exits the program




