The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Language::Prolog::Yaswi - Yet another interface to SWI-Prolog

SYNOPSIS

use Language::Prolog::Yaswi ':query';
use Language::Prolog::Types::overload;
use Language::Prolog::Sugar functors => { equal => '=',
                                          is    => 'is' },
                            chains => { orn => ';',
                                        andn => ',',
                                        add => '+' },
                            vars => [qw (X Y Z)];

swi_set_query( equal(X, Y),
               orn( equal(X, 27),
                    equal(Y, 'hello')));

while (swi_next) {
    printf "Query=".swi_query()."\n";
    printf "  X=%s, Y=%s\n\n", swi_var(X), swi_var(Y);
}

print join("\n",
          swi_find_all(andn(equal(X, 2),
                            orn(equal(Y, 1),
                                equal(Y, 3.1416)),
                            is(Z, add(X,Y,Y))),
                       [X, Y, Z]));

ABSTRACT

Language::Prolog::Yaswi implements a bidirectional interface to the SWI-Prolog system (http://www.swi-prolog.org/).

DESCRIPTION

This package provides a bidirectional interface to SWI-Prolog. That means that Prolog code can be called from Perl that can call Perl code again and so on:

Perl -> Prolog -> Perl -> Prolog -> ...

(unfortunately, by now, the cycle has to be started from Perl, although it is very easy to circumvent this limitation with the help of a dummy Perl script that just calls Prolog the first time).

The interface is based on the set of classes defined in Language::Prolog::Types. Package Language::Prolog::Sugar can also be used to improve the look and readability of scripts mixing Perl and Prolog code.

The interface to call Prolog from Perl is very simple, at least if you are used to Prolog non deterministic nature.

SUBROUTINES

Grouped by export tag:

:query
swi_set_query($query1, $query2, $query3, ...)

Composes a query with all the parameters given and sets it.

The set of free variables found in the query is returned.

swi_set_query_module($query, $module)

Allows to set a query in a module different than the default.

swi_result

Returns the values binded to the variables in the query.

swi_next

Iterates over the query solutions.

If a new solution is available returns true, if not, closes the query and returns false.

It has to be called after swi_set_query(...) to obtain the first solution.

swi_var($var)

Returns the value binded to $var in the current query/solution combination.

swi_vars(@vars)

Returns the values binded to @vars in the current query/solution combination.

Actually, it accepts more powerfull contructions, i.e.

$a = swi_vars([X, Y, [Z]])
swi_query

Returns the current query with the variables binded to its values in the current solution (or unbinded if swi_next has not been called yet).

swi_cut

Closes the current query even if not all of its solutions have been retrieved. Similar to prolog cut (!).

swi_find_all($query, @pattern)

iterates over $query and returns and array with @pattern binded to every solution. i.e:

swi_find_all(member(X, [1, 3, 7, 21]), X)

returns the array (1, 3, 7, 21) and

swi_find_all(member(X, [1, 3, 7, 21]), [X])

returns the array ([1], [3], [7], [21]).

More elaborate constructions can be used:

%mothers = swi_find_all(mother(X,Y), X, Y)

There is also an example of its usage in the SYNOPSIS.

swi_find_one($query, @pattern)

as swi_find_all but only for the first solution.

swi_call($query)

runs the query once and returns true if a solution was found or false otherwise.

swi_parse(@strings)

commodity interface to prolog predicate atom_to_term/3. Converts strings to prolog terms.

swi_eval(@strings)

parses @strings and calls them on the prolog engine.

:interactive
swi_toplevel

mostly for debugging pourposes, runs SWI-Prolog shell.

:load
swi_inline @code

dumps @code to a temporary file and consults it from prolog.

Use $swi_temp_dir to change the directory where the file is created.

swi_inline_module @code

similar to swi_inline() but using use_module/1 to load the file.

swi_consult @files
swi_use_modules @modules
:assert
swi_assert($head => @body)
swi_assertz($head => @body)

add new definitions at the bottom of the database

swi_asserta($head => @body)

adds new definitions at the top of the database

swi_facts(@facts)

commodity subroutine to add several facts to the database in one call (a fact is a predicate with an empty body).

i.e.:

use Language::Prolog::Sugar functors=>[qw(man woman)];

swi_facts( man('teodoro'),
           man('socrates'),
           woman('teresa'),
           woman('mary') );
swi_retractall(@heads)

loops over @heads calling retractall/1 Prolog predicate.

:context
$swi_module

allow to change the module for the upcoming queries.

use the local operator when changing their values ALWAYS!!!

i.e.:

local $swi_module='mymodule'
swi_set_query($query_from_mymodule);
$swi_converter

allows to change the way data is converter from Perl to Prolog.

You should really not use it for anything different than configuring perl classes as opaque, i.e.:

$swi_converter->pass_as_opaque(qw(LWP::UserAgent
                                  HTTP::Request
                                  HTTP::Result))

... unless you know what you are doing!!!

$swi_temp_dir

see docs for swi_inline()

:run
swi_init(@args)

lets init the prolog engine with a different set of arguments (identical to the command line arguments for the pl SWI-Prolog executable.

Defaults arguments are -q to stop the SWI-Prolog welcome banner for being printed to the console.

Language::Prolog::Yaswi will automatically create a new engine with the default arguments (or with the last passed via swi_init), when needed.

swi_cleanup

releases the prolog engine.

Language::Prolog::Yaswi will release the engine when the script finish, this function is usefull to release the engine to free resources or to be able to init it again with a different set of arguments.

CALLBACKS

Yaswi adds to SWI-Prolog three new predicates to call perl back.

All the calls are made in array contest and the Result value is always a list. There is no way to make a call in scalar context other than explicitly calling scalar.

perl5_eval(+Code, -Result)

evaluates the Perl code passed on the atom Code and return the results as a list in Result.

perl5_call(+Sub, +Args, -Result)

calls the Perl sub Sub with the arguments in the list Args and returns the list of results in Result.

perl5_method(+Object, +Method, +Args, -Result)

calls the method Method from the perl object Object.

To get a Perl object passed to prolog as an opaque value instead of marshaled into prolog types, its class (or one of its parent classes) has to be previously registered as opaque with the $swi_converter object. i.e.:

perl5_eval('$Language::Prolog::Yaswi::swi_converter \
             -> pass_as_opaque("HTTP::Request")',_),
perl5_eval('use HTTP::Request',_),
perl5_method('HTTP::Request', new, [], [Request]),
perl5_method(Request, as_string, [], [Text]).

Registering class UNIVERSAL causes all objects to be passed as opaques to prolog.

EXPORT

This module doesn't export anything by default. Subroutines should be explicitely imported.

THREADS

To get thread support in this module both Perl and SWI-Prolog have to be previously compiled with threads. Perl needs the ithread model available from Perl version 5.8.0 and upwards.

When Perl is called back from a thread created from Prolog a new fresh Perl engine is constructed. That means there will be no modules preloaded on it, no access to Perl data from other threads (not even data marked as shared!), etc. Threads created from Perl do not suffer from this limitation.

KNOWN BUGS

It is not possible to use Prolog C extensions (i.e. pce) in every OS. Though it works at least on Linux, Solaris and Windows.

Unicode support is experimental.

Variable attributes are discarded when they cross the Perl/Prolog interface.

SEE ALSO

SWI-Prolog documentation http://www.swi-prolog.org/, pl(1), Languages::Prolog::Types and Language::Prolog::Sugar.

AI::Prolog is a well maintained Prolog implementation in pure Perl.

COPYRIGHT AND LICENSE

Copyright 2003-2006, 2008, 2011, 2012 by Salvador Fandiño <sfandino@yahoo.com>

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