[comp.lang.prolog] taking a predicate name as an argument

eaiu088@orion.oac.uci.edu (Alisa Tannirat) (04/13/90)

how do i take a predicate name as an argument and use it as a basis for
selecting an operation on the other arguments?

for example, 

question(+, X, Y, Answer):-
  Answer is X + Y.

question(*, X, Y, Answer):-
  Answer is X * Y

i would like question to be general enough to take any operator and perform
it on X and Y resulting in Answer.

please e-mail me, the information would be appreciated.

alisa tannirat

pgl@cup.portal.com (Peter G Ludemann) (04/14/90)

> how do i take a predicate name as an argument and use it as a basis for
> selecting an operation on the other arguments?
>	[ e.g.: question('+', X, Y, Answer) :- Answer is X + Y . ]
> i would like question to be general enough to take any operator and perform
> it on X and Y resulting in Answer.

The general solution to this question in IBM-Prolog is
(using its Edinburgh syntax):

        question(Pred, X, Y, Answer) :- Answer is Pred(X,Y) .

or even more compactly using its standard syntax:

        question(Pred, X, Y, ? Pred(X,Y)) .

However, this solution is not readily available in other
Prologs because:

- Functor names can't be variables.  It would seem that this
  could be overcome by using =../2:

        question(Pred, X, Y, Answer) :-
                F =.. [Pred, X, Y],
                Answer is F .

- But general terms aren't allowed with "is" (at least, this is
  the case with Quintus 2.x; I assume it's true of others); if	
  you try this, you will get a run-time error for is/2. 

So, the answer would seem to be "it can't be done" in many
popular Prologs; you'll just have to list out all the arithmetic
operators yourself (there aren't too many, fortunately).

Peter Ludemann     IBM Prolog Development (these are my opinions, not IBM's)
 

ken@aiai.ed.ac.uk (Ken Johnson) (04/14/90)

In article <2624D004.805@orion.oac.uci.edu> eaiu088@orion.oac.uci.edu
(Alisa Tannirat) writes:

% how do i take a predicate name as an argument and use it as a basis for
% selecting an operation on the other arguments?
% 
% for example, 
% 
% question(+, X, Y, Answer):-
%   Answer is X + Y.
% 
% question(*, X, Y, Answer):-
%   Answer is X * Y
% 
% i would like question to be general enough to take any operator and perform
% it on X and Y resulting in Answer.

question(Functor,Arg1,Arg2,Answer) :-
	functor(Term,Functor,2),
	arg(1,Term,Arg1),
	arg(2,Term,Arg2),
	Answer is Term.


% E mail bounces so often from here that I'm posting this anyway.
% Good luck. Email me directly and let me know if it worx.




-- 
Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212
`I have read your article, Mr Johnson, and I am no wiser now than when I
started'.  -- `Possibly not, sir, but far better informed.'

dave@quintus.UUCP (David Bowen) (04/15/90)

In article <28908@cup.portal.com> pgl@cup.portal.com (Peter G Ludemann) writes:
>- Functor names can't be variables.  It would seem that this
>  could be overcome by using =../2:
>
>        question(Pred, X, Y, Answer) :-
>                F =.. [Pred, X, Y],
>                Answer is F .
>
>- But general terms aren't allowed with "is" (at least, this is
>  the case with Quintus 2.x; I assume it's true of others); if	
>  you try this, you will get a run-time error for is/2. 
>
>So, the answer would seem to be "it can't be done" in many
>popular Prologs; you'll just have to list out all the arithmetic
>operators yourself (there aren't too many, fortunately).

It can be done, like this:

        question(Pred, X, Y, Answer) :-
                 F =.. [Pred, X, Y],
                 call(Answer is F).

In future releases of Quintus Prolog it won't be necessary to put in the
call/1 wrapper.

If efficiency is of any concern, though, it would be better to have a 
clause for each arithmetic operator as Peter suggested.

jeff@aiai.ed.ac.uk (Jeff Dalton) (05/26/90)

In article <1372@quintus.UUCP> pds@quintus.UUCP (Peter Schachte) writes:
>In article <2537@skye.ed.ac.uk> jeff@aiai.UUCP (Jeff Dalton) writes:
>>I'm not sure just what kind of atom-based thinking I'm supposed to be
>>guilty of.  In the past, it's been claimed that atoms are different in
>>Lisp because of property lists, or something like that.
>
>Lisp has lots of things that can be defined (e.g., functions, macros,
>variables, structures, ...) which need to be put into packages.  So
>maybe it was thought to be easier to modularize Lisp by putting symbols
>in packages, rather than by putting definitions into packages.
>
>That argument doesn't apply to Prolog, however, since Prolog programs
>only define predicates.

I guess the first thing to say is that, as far as I know, none of my
statements in favor of atom-based schemes have been the result of
applying this sort of many-namespace thinking to Prolog.

The second thing to say is that some versions of Lisp have only
one namespace.  That is, there's only one mapping from names to
values instead of the several there are in Common Lisp.

Indeed, even in a Lisp with several namespaces it's still possible for
modules to come between symbols and values (so to speak) rather than
between source text and symbols (which is more or less what happens in
packages).

You're probably right that it's easier to take the package approach
in Lisp.  It's taken a while for the Scheme folk to come up with
good alternatives that fit well with macros, and more work would be
required in order to adapt such ideas to Common Lisp.  It's probably
easier in Prolog too.

However, one important factor in favor of packages turns out to be
fairly analogous to what happens in Prolog.  That is, in Common Lisp
it's possible to pass symbols as functional arguments as well as being
able to pass actual function objects.  For example, I can say:

   (mapcar 'f '(a b c))

It would be nice if F were already resolved with respect to modules
so that it would be clear which function in which module it meant.
Similarly, in Prolog, one can pass terms, or even atoms which get
made into terms via =.., and call them using call/1.  So it would
be nice if terms (and atoms) were already resolved with respect
to modules.

This argument doesn't apply to Scheme, because in Scheme you can
use only actual function objects in this way.  However, similar
problems appear when you introduce macros.  For example, if a
macro call expands into

   (mapcar f '(a b c))

it would be nice to know which F (and which MAPCAR) in which
module was meant.

Some rather complex renaming or syntactic closure mechanisms
are used to deal with such problems.  I would like to think there
was some way to deal with them in Prolog and that we just haven't
discovered it yet.

-- Jeff