From: Peter Ludemann <ludemann@quintus.com>
Subject: Re: Different Strokes for Different Folks (Was: Assessing a language)
Reply-To: Peter Ludemann <ludemann@quintus.com>
Organization: Compilers Central
Date: Fri, 22 Jan 1993 03:21:54 GMT
Keywords: prolog, functional

eifrig@beanworld.cs.jhu.edu (Jonathan Eifrig) wrote:
>	Surprisingly, there hasn't been much work in developing
>heterogenous programming environments, to support a sort of "mix and
>match" approach to programming.  Such tools would go a long way to
>alleviating the language holy wars, I think.

This isn't true of some Prolog implementations.  From the user's point of
view, the major integration problem is writing the declarations for the C
functions if calling from Prolog to C; the call from C to Prolog is
usually done through a single procedure call, plus some routines to
manipulate the Prolog structures.

The tricky part from an implementation point of view is dealing with all
the various flavors of object code formats and the "features" of loaders
(dare I say "bugs"?).  If nice dynamic loading isn't desired, the
implementation becomes simpler.  But a major advantage of using more
powerful languages such as Prolog is the rapid edit/load/run cycle, so
it's nice to have dynamic loading of the foreign code.

One of the interesting questions is how to handle the mismatch of
functionality between the two languages.  Data structures are fairly easy
to handle (for example, transforming between Prolog lists and C arrays); a
larger question is how to handle things like backtracking (from Prolog) or
continuations and functional composition (in Scheme or ML).

As an example of handling backtracking in Prolog, we could provide
functions to create backtrack points from C; or we could instead insist
that the C function be wrapped in a Prolog which does the backtracking.
As an example of the latter, here is some (horrible) C code, which
generates successive values between i_first and i_last, giving a return
code of 1 for success and 0 for failure:

int i_first, i_last; /* global variables */

gener_init(first, last) 
int first, last;
{   i_first = first;
    i_last = last;
}

int gener(i) 
int *i;
{   if ( i_first > i_last ) {
        *i = i_last;
        return 0;
    } else {
        *i = i_first++;
        return 1;
    }	
}

Then, we can write in Quintus Prolog a predicate to generate successive
values by the following:

foreign(gener_init, c, gener_init(+integer, +integer)). /*declare C routine */
foreign(gener,      c, gener(-integer, [-integer])).    /*declare C routine */
foreign_file('gener.o', [gener_init, gener]).       /* where to find the .o */
:- load_foreign_files('gener.o', []).                   /*load it */

between(First, Last, I) :- 
    gener_init(First, Last),   /* call C routine to initialize */
    gener(I0, RC),             /* get first result */
    between2(RC, I0, I).       /* check result */

between2(1, I, I).             /* result OK */
between2(1, _, I) :-           /* backtrack */
    gener(I0, RC),             /* gener new value from C */
    between2(RC, I0, I).       /* and check it */

The alternative to this is to allow declaring a backtrack point from
inside C, which requires exposing more of the Prolog system's internals to
the interface.

The above example isn't very useful, but it indicates how to build an
interface to a database, getting successive rows by backtracking.

Two Prolog implementations that have good foreign language interfaces are
IBM Prolog (CMS, MVS, OS/2) and Quintus Prolog (Unix, DOS).  No doubt
there are others.
-----
Peter Ludemann 				Manager, Large Applications Consulting
Quintus Corporation                     InterNet:       ludemann@quintus.com
2100 Geng Road                          FAX:            +1-415-494-7608
Palo Alto, California 94303             Phone:          +1-415-813-3819
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.
Newsgroups: comp.compilers