Is there support in AI::Prolog for calling back into perl? I wanted to write a program like this the other day but couldn't because I couldn't make a rule that would be a real function call back into perl.

% Perl callbacks
% doUnlockInvoice/1
% doUnlockConfirm/1
% doRegenConfirm/1
% doRollback/1

rollbackGenarg( A ) :-
        adjustGenarg( A, B ),
        rollbackGenarg( B ),
        !, fail.
rollbackGenarg( G ) :-
        lockedInvoices( G, I ),
        not( confirmInvoice( I ) ),
        doUnlockInvoice( I ),
        !, fail.
rollbackGenarg( G ) :-
        lockedInvoices( G, I ),
        isConfirm( I ),
        processedConfirm( I ),
        doUnlockConfirm( I ),
        !, fail.
rollbackGenarg( G ) :-
        lockedInvoices( G, I ),
        isConfirm( I ),
        not( processedConfirm( I ) ),
        doRegenInvoice( I ),
        !, fail.
rollbackGenarg( G ) :-
        not( adjustGenarg( G, _ ) ),
        not( lockedInvoices( G, _ ) ),
        doRollback( G ).
I've had requests for similar behavior, but they've been rather nebulous. What I would need is a small, concrete example of what you would need. The major obstacle is that you would have to provide callbacks which are either guaranteed to not have side-effects or, barring that, have deterministic behavior on backtracking.

For example, on the no-side-effects rule, a callback which deletes a file would likely be problematic as you can't delete a file more than once. Having an "or die" would would kill the program.

For deterministic behavior on backtracking, I mean something like an iteratative function such as DBI functions which would return rows from the database and then you could walk forward a few rows and then walk back and not worry that the data has changed in the mean time.

For the simple examples you give, they seem clear enough that this seems like something I could potentially do. Still, something like this would be a nice test case for what's needed in Perl 6.
Ok, it would be a lighter burden to have either no side effects or to postpone actions til success occurs.

I imagine that in most cases I wouldn't be interested in writing any backtracking ability. This means I'd want to postpone the irrevocable part of the action til later or put a cut immediately afterward. I imagine these varying levels of support could be easily tagged for the prolog engine.

Consider the associated attributes for a function when calling it. Maybe with the attribute :side_effect_safe, it can be called directly. Maybe memoized. Whatever. Take liberties with it in your code. With the attribute :rewrite_with_cut, assume there's a side effect and rewrite your prolog assertions so success is followed by a cut to prevent backtracking. With the attribute :ok_for_backtracking you'd trust that if there are side effects, they'll be backed out.

Heck, maybe there'd be another attributed subroutine type which is expected to return a code reference to AI::Prolog. If the query succeeds, the code reference is called. Then it isn't even done until things are already done.
Oh. Further, maybe the attribute has the arity. I'm focusing on the user's interface to your code, not the guts of your code or the verbose, non-attribute way of getting there. I think it would suck to have to write a whole other function call to register my call backs when I could just tag whem thith attributes.

You know what? I just had an epiphany about how to make this work. It wouldn't be available from the AI::Prolog shell, but it wouldn't make much sense there anyway. The basic idea would look like this:

AI::Prolog->callbacks(
   "doUnlockInvoice/1" => \&doUnlockInvoice,
   "doUnlockConfirm/1" => \&doUnlockConfirm,
   "anotherCallback/2" => \&anotherCallback,
);

And the the actual code would be registered with AI::Prolog::Engine::Primitives

$PRIMITIVES[34] = sub { # callback
    my ($self, $term) = @_;
    my $callback = $self->_callbacks($term->predicate);
    my @args     = map { $term->getarg($_)->value } 0 .. ($term->arity - 1);
    return $callback->(@args) ? CONTINUE : FAIL;
};

Now that I stop to think about it, that won't do a great job with unification. Ugh. Still, I think it's on the right track.