Search code examples
prolog

What are the functors of compound sub terms of a Prolog term?


PreCond: true.

I am trying to do this functor compounds term Given the precondition (PreCond) of the predicate, the search trees of the appropriate goals must be finite. Provided a test with some solutions given, the program should produce the same bag of solutions, possibly in a different order.

%% functorOfCompoundSubterm(T,FN) :-
%%     FN is the functor of some compound subterm of T.

%% I want to Avoid the double compound check of the same subterm, i.e.,
%%       if S is a subterm of T, its compound' property should be
%%       checked only once during the run of this predicate call.
%%
%% LI (for all the solutions together):
%%    O(n) where n is the number of subterms of T.

%% And this is my implementation Solution:
functorOfCompoundSubterm( T, FN ) :-
  compound(T),
  functorOfCompoundSubterm__(T,FN).

functorOfCompoundSubterm__( T, FN ):-
  functor(T,F,N) ,
  FN = F/N ,
  arg(_N,T,X) ,
  functorOfCompoundSubterm__(X,FN).

and when I try to run the goals it shows this error

% Goals 
| ?- functorOfCompoundSubterm(a(b(G,1,c(2)),3,d(e(4,g),5)),F/4).
no
% source_info,3
| ?- functorOfCompoundSubterm(a(b(G,1,c(2)),3,d(e(4,g),5)),F/2).
no
% source_info,3
| ?- 

While the expected result is

F = d ? ;
F = e ? ;
no

Another expected test

| ?- functorOfCompoundSubterm(a(b(G,1,c(2)),3,d(e(4,g),5)),FN).
FN = a/3 ? ;
FN = b/3 ? ;
FN = c/1 ? ;
FN = d/2 ? ;
FN = e/2 ? ;
no

and it shows this error when trying to execute the goal

| ?- | ?- functorOfCompoundSubterm(a(b(G,1,c(2)),3,d(e(4,g),5)),FN).
! Syntax error
! | cannot start an expression
! in line 374
! <<here>>
! | ?- functorOfCompoundSubterm ( a ( b ( G , 1 , c ( 2 ) ) , 3 , d ( e ( 4 , g ) , 5 ) ) , FN ) . 
| ?- 

Solution

  • You may do this:

    functor_of_compound(T, FN):-
      compound(T),
      T=..[Functor|Args],
      functor_of_compound(Functor, Args, FN).
      
    functor_of_compound(Functor, Args, Functor/Arity):-
      length(Args, Arity).
    functor_of_compound(_, Args, FN):-
      member(T, Args),
      functor_of_compound(T, FN).
    

    If the term is compund, then decompose it and yield its Functor/Arity and upon backtracking traverse each argument recursively.

    Sample run:

    ?- functor_of_compound(a(b(G,1,c(2)),3,d(e(4,g),5)),FN).
    FN = a/3 ;
    FN = b/3 ;
    FN = c/1 ;
    FN = d/2 ;
    FN = e/2 ;
    false.