AI-Prolog
view release on metacpan or search on metacpan
lib/AI/Prolog.pm view on Meta::CPAN
package AI::Prolog;
$VERSION = '0.741'; ## no critic
use strict;
use Carp qw( confess carp croak );
use Hash::Util 'lock_keys';
use Exporter::Tidy shortcuts => [qw/Parser Term Engine/];
use aliased 'AI::Prolog::Parser';
use aliased 'AI::Prolog::Term';
use aliased 'AI::Prolog::Engine';
use Text::Quote;
use Regexp::Common;
# they don't want pretty printed strings if they're using this interface
Engine->formatted(0);
# Until (and unless) we figure out the weird bug that prevents some values
# binding in the external interface, we need to stick with this as the default
Engine->raw_results(1);
sub new {
my ( $class, $program ) = @_;
my $self = bless {
_prog => Parser->consult($program),
_query => undef,
_engine => undef,
} => $class;
lock_keys %$self;
return $self;
}
sub do {
my ( $self, $query ) = @_;
$self->query($query);
1 while $self->results;
$self;
}
sub query {
my ( $self, $query ) = @_;
# make that final period optional
$query .= '.' unless $query =~ /\.$/;
$self->{_query} = Term->new($query);
unless ( defined $self->{_engine} ) {
# prime the pump
$self->{_engine} = Engine->new( @{$self}{qw/_query _prog/} );
}
$self->{_engine}->query( $self->{_query} );
return $self;
}
sub results {
my $self = shift;
unless ( defined $self->{_query} ) {
croak "You can't fetch results because you have not set a query";
}
$self->{_engine}->results;
}
sub trace {
my $self = shift;
if (@_) {
$self->{_engine}->trace(shift);
return $self;
}
return $self->{_engine}->trace;
}
sub raw_results {
my $class = shift;
if (@_) {
Engine->raw_results(shift);
return $class;
}
return Engine->raw_results;
}
my $QUOTER;
sub quote {
my ( $proto, $string ) = @_;
$QUOTER = Text::Quote->new unless $QUOTER;
return $QUOTER->quote_simple($string);
}
sub list {
my $proto = shift;
return
join ", " => map { /^$RE{num}{real}$/ ? $_ : $proto->quote($_) } @_;
}
sub continue {
my $self = shift;
return 1 unless $self->{_engine}; # we haven't started yet!
!$self->{_engine}->halt;
}
1;
__END__
=head1 NAME
AI::Prolog - Perl extension for logic programming.
=head1 SYNOPSIS
use AI::Prolog;
use Data::Dumper;
my $database = <<'END_PROLOG';
append([], X, X).
append([W|X],Y,[W|Z]) :- append(X,Y,Z).
END_PROLOG
my $prolog = AI::Prolog->new($database);
my $list = $prolog->list(qw/a b c d/);
$prolog->query("append(X,Y,[$list]).");
while (my $result = $prolog->results) {
print Dumper $result;
}
=head1 ABSTRACT
AI::Prolog is merely a convenient wrapper for a pure Perl Prolog compiler.
Regrettably, at the current time, this requires you to know Prolog. That will
change in the future.
=head1 EXECUTIVE SUMMARY
In Perl, we traditionally tell the language how to find a solution. In logic
programming, we describe what a solution would look like and let the language
find it for us.
=head1 QUICKSTART
For those who like to just dive right in, this distribution contains a Prolog
shell called C<aiprolog> and two short adventure games, C<spider.pro> and
C<sleepy.pro>. If you have installed the C<aiprolog> shell, you can run
either game with the command:
aiprolog data/spider.pro
aiprolog data/sleepy.pro
When the C<aiprolog> shell starts, you can type C<start.> to see how to play
the game. Typing C<halt.> and hitting return twice will allow you to exit.
See the C<bin/> and C<data/> directories in the distribution.
Additionally, you can read L<AI::Prolog::Article> for a better description of
how to use C<AI::Prolog>. This document is an article originally published in
( run in 1.525 second using v1.01-cache-2.11-cpan-39bf76dae61 )