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