[comp.lang.prolog] Why no macro facility?

daven@lll-crg.llnl.gov (Dave Nelson) (07/08/88)

Could someone tell me why prolog has no built-in macro facility?
Even the industrial strength, full-featured prolog I am currently
evaluating doesn't have such a thing.

This sort of source-to-source transformation of files, *which can then
be compiled*, is the LISP feature I miss the most (so far :-).

Oh, and another thing...would it be so hard to put in a compile(pred, arity)
to take a currently interpreted predicate and compile it?  All the
compile(frob) directives interpret frob as a filename.

daven (Dave Nelson)


daven (Dave Nelson)
arpa:  daven @ lll-crg.llnl.gov
uucp:  ...{seismo,gymble,mordor,sun,lll-lcc}!lll-crg!daven

lang@zeta.PRC.Unisys.COM (Francois-Michel Lang) (07/08/88)

In article <9671@lll-winken.llnl.gov> daven@lll-crg.llnl.gov (Dave Nelson) writes:
>Could someone tell me why prolog has no built-in macro facility?
>Even the industrial strength, full-featured prolog I am currently
>evaluating doesn't have such a thing.
>
>This sort of source-to-source transformation of files, *which can then
>be compiled*, is the LISP feature I miss the most (so far :-).

I've never heard of a real macro facility in any Prolog, but
the Prolog system I use (Quintus Prolog 2.2, which is about as
"industrial strength" as they come) has a built-in predicate called
expand_term/2 (which calls the user-defined predicate term_expansion/2)
which can be used as a preprocessor to do source-to-source transformation.
This is, in fact, how Prolog DCGs are translated into vanilla Prolog.

>Oh, and another thing...would it be so hard to put in a compile(pred, arity)
>to take a currently interpreted predicate and compile it?  All the
>compile(frob) directives interpret frob as a filename.

In Quintus Prolog, there's no built-in predicate like that,
but the Emacs-based development environment allows incremental
or piecemeal compiling (and consulting) of files.
So, for example, if you have a file all of whose predicates are
currently interpreted, but you want to compile foo/1 and bar/2
(but leave the rest of the predicates interpreted, that's very
easy to do.

----------------------------------------------------------------------------
Francois-Michel Lang
Paoli Research Center, Unisys Corporation lang@prc.unisys.com (215) 648-7256
Dept of Comp & Info Science, U of PA      lang@cis.upenn.edu  (215) 898-9511

finin@antares (Tim Finin) (07/08/88)

In article <9671@lll-winken.llnl.gov>, daven@lll-crg (Dave Nelson) writes:
>Could someone tell me why prolog has no built-in macro facility?
>Even the industrial strength, full-featured prolog I am currently
>evaluating doesn't have such a thing.
>
>This sort of source-to-source transformation of files, *which can then
>be compiled*, is the LISP feature I miss the most (so far :-).
>...

The various Prolog systems developed by ZYX, including the one
developed for and marketed by HP, do have macro facilities.

Tim

Tim Finin			finin@prc.unisys.com
Paoli Research Center		..!{psuvax1,sdcrdcf,cbmvax,bpa}!burdvax!finin
Unisys Corporation		215-648-7446 (o)  
PO Box 517, Paoli PA 19301	215-386-1749 (h)

kale@m.cs.uiuc.edu (07/09/88)

I don't know what exactly you want in a macro-facility,
but SBProlog does have a macro facility.
You define macros with ::- instead of a :-.
Ask debray@arizona.edu for more information about SBProlog.

ok@quintus.uucp (Richard A. O'Keefe) (07/09/88)

In article <9671@lll-winken.llnl.gov> daven@lll-crg.llnl.gov (Dave Nelson) writes:
>Could someone tell me why prolog has no built-in macro facility?
>Even the industrial strength, full-featured prolog I am currently
>evaluating doesn't have such a thing.
>
If the Prolog you are evaluating hasn't got the term_expansion/2 hook
(which first saw the light of day in C-Prolog years ago) it is not
"full-featured".  You can use term_expansion/2 to plug in any macro
system you like (see my "Practical Prolog for Real Programmers"...).
[Note that a hook into "assert" as some Prologs have just isn't good
enough; you would like to be able to process things that will never
go into the data base.]

There is a "right" way to do macros in Prolog, but getting all the
details right (interaction with cut, ..., what should debugger see, ...)
is a pain.  Lisp is a *wonderful* source of inspiration for this work:
it gets so many things wrong.

Stony Brook Prolog (available from Saumya Debray at the University of
Arizona) contains a macro facility which takes the right approach, but
there are a lot of fiddly details which need a lot more thought.

>This sort of source-to-source transformation of files, *which can then
>be compiled*, is the LISP feature I miss the most (so far :-).

If you were using Quintus Prolog or SB Prolog you wouldn't be missing it.

>Oh, and another thing...would it be so hard to put in a compile(pred, arity)
>to take a currently interpreted predicate and compile it?  All the
>compile(frob) directives interpret frob as a filename.

The absence of ensure_compiled(Name/Arity) -- please, NOT another name botch
like abolish/2 -- is an historical accident: DEC-10 Prolog had the compiler
and interpreter in different "high segments", so the compiler would have
found it hard to get at interpreted code.  In ALS Prolog and NIP and some
others, such an operation would be completely pointless, as there is no
distinction between compiled and interpreted code.  ZYX Prolog does have
such an operation.  (Unfortunately, they called it compile/1, which does
rather nasty things to programs that want to compile files.  Boo hiss.)

In DEC-10 Prolog and its successors, you can do

my_compile(Preds) :-
	tell('SCRTCH.PL'),	% oh, those DEC 6.3 file-names...
	listing(Preds),
	told,
	compile('SCRTCH.PL').

chik@icot21.icot.JUNET (Chikayama Takashi) (07/11/88)

The language ESP (a language consisting of Prolog + Object-oriented
features, running on the Prolog machine PSI) does have macro expansion
facility.  The language has been used for 4 years already for various 
software in the Japanese FGCS project.

Difficulty in macro processing in Prolog is that literal replacement
as seen in macro expansion for the language C, or expansion of
individual terms in the clauses, will never be enough.  More 
structural approach is needed.

With our macro:
	p(X) :- q(f(X+3)).			(1)
can be expanded to:
	p(X) :- Y is X+3, q(f(Y)).		(1e)
Note that "X+3" is NOT expanded in its original place.
Also, such a macro as to expand:
	p(X) :- q(X, Y!integer).		(2)
to:
	p(X) :- q(X, Y), integer(Y).		(2e)
can also be defined.  Note that, in (1e) and (2e), an extra goal is 
inserted in different places: before and after the goal in which the 
macro invocation appears.

The macro mechanism also helps to eliminate higher-level predicates. 
For example, consider a program with higher level predicate "mapcar":
	p(L0, L) :- mapcar(L0, q, L).
where:
	mapcar([], _, []).
	mapcar([X|L0], P, [Y|L]) :-
		Goal =.. [P,X,Y],
		call(Goal),
		mapcar(L0, P, L).
As "call/1" cannot but be interpretive, you may want to rewrite it (by
hand, maybe) for efficiency as:
	p(L0, L) :- mapcar_q(L0, L).
	mapcar_q([], []).
	mapcar_q([X|L0], [Y|L]) :-
		q(X, Y),
		mapcar_q(L0, P, L).
This transformation can be automatically done by our macro expansion
mechanism, if "mapcar" is defined as a macro properly.

DCG can be defined using the same mechanism.

More details will appear in the Seattle conference:

	Sei-ichi Kondo and Takashi Chikayama:
	"Macro processing in Prolog"

Takashi Chikayama (ICOT)

dowding@macbeth.PRC.Unisys.COM (John Dowding) (07/13/88)

In article <9671@lll-winken.llnl.gov> daven@lll-crg.llnl.gov (Dave Nelson) writes:
>Could someone tell me why prolog has no built-in macro facility?
>Even the industrial strength, full-featured prolog I am currently
>evaluating doesn't have such a thing.
>
>daven (Dave Nelson)
>

I did some experiements with this kind of thing with a parser and found that 
it slowed the program down.  I think that this is because current Prolog compilers
dont handle very large clauses well.  Consider this example:

p(X):-
    q(X),
    r(X),
    s(Y).

q(tree(_,_,_,_)).


If we turn q into a macro, then the resulting clause for p is:

p(tree(A,B,C,D)):-
    r(tree(A,B,C,D)),
    s(tree(A,B,C,D)).


Note also that where there use to be a single variable X that pointed to the
structure tree/4, now there isnt.

In my application, the use of macros made the size of the resulting clauses enormous.
The resulting program ran as much as 2 times slower than the version with
procedure calls.

John Dowding

dowding@prc.unisys.com