6

This answer by Jan Burse shows one of the simplest implementations of a metainterpreter in Prolog:

solve(true) :- !.
solve((A,B)) :- !, solve(A), solve(B).
solve(H) :- clause(H,B), solve(B).

I would like to extend this interpreter so that it can call builtins. The vanilla one isn't able to handle calls such as solve(member(X, [1,2,3,4])). Is this possible using ISO predicates? If not, is it possible using SWI-Prolog predicates?

false
  • 10,264
  • 13
  • 101
  • 209
Daniel Lyons
  • 22,421
  • 2
  • 50
  • 77
  • In some Prolog systems, the more ISO compatible ones, you need to mark the predicates dynamic, so that clause/2 can find them. This is SWI-Prolog specific that it returns also static predicates. –  Apr 03 '19 at 18:02

2 Answers2

3

I think predicate_property/2 may be useful for your task.

As the name already implies, this predicate relates a predicate (head) to one ore more properties.

For example:

?- predicate_property((A,B), P).
P = interpreted ;
P = visible ;
P = built_in ;
P = static ;
P = imported_from(system) ;
etc.

From such properties, you can deduce whether a predicate is built-in, and the call it directly.

It is also available in SICStus.

Beware though: Not all built-in predicates retain their semantics when called directly. I think discussing what they are and how to interpret them would be well worth its own question.

mat
  • 40,498
  • 3
  • 51
  • 78
2

Stackoverflow is refusing to accept my answer :) that was

Just call/1 them

Edit

For instance

?- [user].
solve(true) :- !.
|: solve((A,B)) :- !, solve(A), solve(B).
|: solve(H) :- clause(H,B), solve(B).
|: solve(T) :- call(T).
|: ^Dtrue.

?- solve(member(X, [1,2,3,4])).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4.

The only addition: solve(T) :- call(T).

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • This solution leaves a choice point, and then calls predicates twice. I now get: ?- solve(pet(X)). X = cat ; X = cat ; X = cat ; X = cat ; X = cat ; false. Instead only ?- solve(pet(X)). X = cat ; false. –  Apr 03 '19 at 18:24