Re: A programming question

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 08/19/2013 09:06 AM, Norbert E. Fuchs wrote:
>
> Hi
>
> To collect all terms of the form skX/{0-N} – where X is a number 1, 2, ... and the term can have any number of arguments – that occur in Term I use the call
>
> (*)   findall(Skolem, (subterm(Skolem, Term), functor(Skolem, Functor, _Arity), atom_chars(Functor, [s,k|_])), Skolems)
>
> where
>
> subterm(Term, Term) :-
>   nonvar(Term).
>
> subterm(Sub, Term):-
>   nonvar(Term),
>   functor(Term, _F, N),
>   N > 0,
>   subterm(N, Sub, Term).
>
>
> subterm(N, Sub, Term):-
>   arg(N, Term, Arg),
>   subterm(Sub, Arg).
>
> subterm(N, Sub, Term):-
>   N>1,
>   N1 is N-1,
>   subterm(N1, Sub, Term).
>
>
> Since the call (*) occurs in several places in my program and is used very often, I wonder about its efficiency.
>
> Any suggestions how to speed up the call? Is replacing functor/3 by univ a good idea? Should I replace the general subterm/2 by a specialised form that takes the form of the subterm into account?

The system def of sub_term/2 is this:

sub_term(X, X).
sub_term(X, Term) :-
	compound(Term),
	arg(_, Term, Arg),
	sub_term(X, Arg).

And to see whether an atom starts with sk, I'd use sub_atom(Atom, 0, _,
_, sk).  That does not
create any intermediate data structures.

Finally, performance of simple meta-calls is better than control
structures.  There is
a flag (compile_meta_arguments) that you can set to make the system
generate the
intermediate predicate for you.  So, I would write

:- set_prolog_flag(compile_meta_arguments, control).

	...,
	findall(Skolem, ( sub_term(Skolem, Term),
	                  compound(Skolem),
			  functor(Skolemn, Name, _),
			  sub_atom(Name, 0, _, _, sk)
			),
		Skolemns)

Yet, better might be the nice forward loop, which avoid
copying and setup/finalize of the findall.

skolemns(Term, Skolems) :-
	skolemns(Term, Skolems, []).

skolemns(Term, Skolems, Tail) :-
	compound(Term), !,
	functor(Term, Name, Arity),
	(   sub_atom(Name, 0, _, _, sk)
	->  Skolems = [Term|Tail]
	;   skolemn_args(1, Arity, Term, Skolems, Tail)
	).
skolemns(_, Skolems, Skolems).

<guess you can do skolemn_args>

	Cheers --- Jan
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.