=head1 NAME

AI::Prolog::Builtins - Builtin predicates that AI::Prolog supports

=head1 REVISION

 $Id: Builtins.pod,v 1.7 2005/02/28 02:57:17 ovid Exp $

=head1 MATH

Math has been available in L<AI::Prolog> since version 0.62.  It is hoped that
it is fairly robust, but it should be noted that it is implemented via
predicates rather than operators.  This simplified the the implementation
tremendously.

Number may be integers, floats, doubles, etc.  A number that starts with a minus
sign (-) is considered negative.  No number may end in a decimal point as the
period is interpreted as the end of a clause.  The following is therefore a 
syntax error:

 is(X, plus(5, 7.)).

Omit the period after the number or put a zero after it:

 is(X, plus(5, 7)).
 is(X, plus(5, 7.0)).

=head2 Comments

Comments begin with a C<%> and terminate at the end of the line or begin with
C</*> and terminate with C<*/>. 

=head2 Variables

As in Prolog, all variables begin with an upper-case letter and are not quoted.
In the following example, C<STUFF> is a variable.

 steals(badguy, STUFF, "Some rich person").

=head2 Constants

Constants begin with lower-case letters.  If you need a constant that begins
with an upper-case letter or contains spaces or other non-alphanumeric
characters, enclose the constant in single or double quotes  The quotes will
not be included in the constant.

In the following example, C<badguy> and C<Some rich person> are both constants:

 steals(badguy, STUFF, "Some rich person").

=head2 Miscellaneous

This will not work:

 p(X) :- X. /* does not work */

Use this instead:

 p(X) :- call(X).

=head1 BUILTINS

=over 4

=item * C<!>.

The "cut" operator.  This is used when you wish to tell Prolog that you only
need to satisfy a goal once.  For example, if you wish to deny someone the
right to rent videos if they have overdue videos, you might use the cut
operator as soon as you see they have any overdue video.  The fact that they
have more than one overdue video doesn't matter.

See the C<cut.pl> program in the C<examples/> directory that comes with this
distribution.

=item * C<assert(X)>.

Add new facts to the database.  Only facts can be added, not rules.  This may
change in the future.  See C<retract(X)>.

 assert(loves(ovid,perl)).

=item * C<call(X)>.

Invokes C<X> as a goal.

=item * C<div(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X / Y.
Use with C<is(X,Y)>.

 is(X, div(N,3)).

=item * C<eq(X, Y).>

Succeeds if C<X> and C<Y> are equal.

=item * C<fail.>

This goal always fails.  Useful when you've reached a condition you
know should not succeed.

  kill(Hero, Beast) :-
    not(has_weapon(Hero)), fail.

=item * C<ge(X,Y)>.

Succeeds if both terms are bound and X >= Y.

=item * C<gt(X,Y)>.

Succeeds if both terms are bound and X > Y.

=item * C<if(X, Y, Z).>

If C<X> succeeds as a goal, try C<Y> as a goal.  Otherwise, try C<Z>.

 thief(badguy).
 steals(PERP, X) :-
   if(thief(PERP), eq(X,rubies), eq(X,nothing)).

=item * C<is(X,Y).>

If X is unbound and Y is bound to a number, the goal succeeds and  X becomes
bound to the value of Y.  Otherwise, succeeds if both terms are bound, numbers,
and equal.

All other conditions result in failure.

=item * C<le(X,Y)>.

Succeeds if both terms are bound and X <= Y.

=item * C<listing.>

Dumps a listing of all predicates and how they are defined.

=item * C<lt(X,Y)>.

Succeeds if both terms are bound and X < Y.

=item * C<minus(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X - Y.
Use with C<is(X,Y)>.

 is(X, minus(N,1)).

=item * C<mod(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X % Y. (modulus)
Use with C<is(X,Y)>.

 is(X, mod(N,3)).

=item * C<mult(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X * Y.
Use with C<is(X,Y)>.

 is(X, mult(N,3)).

=item * C<nl>

Prints a newline.

=item * C<not(X).>

Succeeds if C<X> cannot be proven.  This is not negation as we're used to
seeing it in procedural languages.

=item * C<notrace.>

Turns off tracing of Prolog's attempt to satisfy goals.

=item * C<once(X)>

Stop solving for C<X> if C<X> succeeds.  Defined as:

 once(X) :- X, !;

=item * C<or(X, Y)>

Succeeds as a goal if either C<X> or C<Y> succeeds.

=item * C<plus(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X + Y.
Use with C<is(X,Y)>.

 is(X, plus(N,1)).

=item * C<print(Term)>.

Prints the current Term.  If the term is an unbound variable, it will print the
an underscore followed by the internal variable number (e.g., "_284").

 print(ovid).         % prints "ovid"
 print("Something").  % prints "Something"
 print(Something).    % prints whatever variable Something is bound to 

=item * C<println(Term)>.

Same as C<print(Term)>, but automatically prints a newline at the end.

=item * C<pow(X,Y)>.

Succeeds if both terms are bound.  The value of the term is X ** Y 
(X raised to the Y power).
Use with C<is(X,Y)>.

=item * C<retract(X)>.

Remove facts from the database.  You cannot remove rules.  This may change in
the future.  See C<assert(X)>.

 retract(loves(ovid,java)).

=item * C<trace.>

Turns on tracing of Prolog's attempt to satisfy goals.

=item * C<true.>

True goal.  Automatically succeeds.

=item * C<var(X)>.

Succeeds if X is an unbound variable.  Otherwise, this goal fails.

=back

=head1 LIMITATIONS

These are known limitations that I am not terribly inclined to fix.  See the
TODO list for those I am inclined to fix.

 IF -> THEN; ELSE not allowed.

Use C<if(IF, THEN, ELSE)> instead.

 = and \= not available.

Use C<eq(X,Y)> and C<not(eq(X,Y))> instead.

=head1 TODO

There are many things on this list.  The core functionality is there, but I do
want you to be aware of what's coming.

=over 4

=item * Anonymous variables

 steals(badguy, _).

Currently, that doesn't work.  Make up a variable name and only use it once.

=item * Improve printing.

There are some bugs with printing and escaping characters.  Maybe I'll look
into them :)

=item * Math.

Math is hard.  So we don't have it, but we will and we'll probably have it in
the form of system predicates that call out to Perl.  We can define most of
what we need logically, but it's very slow and complicated, so we won't do
that.

=back

=head1 BUGS

Currently we cannot directly access bound variables in the tail of a list used
in a query when using unformatted results:

 $prolog->query('foo([Head|Tail], bar).');
 while (my $result = $prolog->results) {
    print Dumper $result->Head;
    print Dumper $result->Tail; # doesn't work
 }

You'll have to switch to C<raw_results> and parse the data manually:

 $prolog->raw_results(1);
 $prolog->query('foo([Head|Tail], bar).');
 while (my $result = $prolog->results) {
     print Dumper $result;
 }    

=head1 SEE ALSO

L<AI::Prolog::Introduction>

L<AI::Prolog>

W-Prolog:  L<http://goanna.cs.rmit.edu.au/~winikoff/wp/>

X-Prolog:  L<http://www.iro.umontreal.ca/~vaucher/XProlog/>

Roman BartE<225>k's online guide to programming Prolog:
L<http://kti.ms.mff.cuni.cz/~bartak/prolog/index.html>

=head1 AUTHOR

Curtis "Ovid" Poe, E<lt>moc tod oohay ta eop_divo_sitrucE<gt>

Reverse the name to email me.

This work is based on W-Prolog, http://goanna.cs.rmit.edu.au/~winikoff/wp/,
by Dr. Michael Winikoff.  Many thanks to Dr. Winikoff for granting me
permission to port this.

=head1 COPYRIGHT AND LICENSE

Copyright 2005 by Curtis "Ovid" Poe

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. 

=cut
