Article View: comp.lang.prolog
Article #3617Seattle tutorial prolog
From: Bart Demoen
Date: Mon, 29 Aug 1988 12:42
Date: Mon, 29 Aug 1988 12:42
114 lines
3892 bytes
3892 bytes
Tutorial No:8 of LP'88 Seattle (R. O'Keefe) makes 'interesting' reading, but
be careful not to believe everything without checking it on the system
you use; here is an example
Section 14 p.159 talks about the foreign interface. It uses gen_symcount/2 as
an example of what you should use the foreign interface for instead of Prolog.
I took the Prolog version mentioned in the tutorial, the version using the
foreign interface mentioned in the tutorial (corrected and adapted to BIMprolog)
and I wrote a version in 'pure BIMprolog'; you find them here, suffixed with C,
B and OK
C version
---------
:- extern_load([make_counter,increment_counter] , ['t.o']) .
:- extern_predicate(make_counter(pointer : r)) .
:- extern_predicate(increment_counter(integer : r , pointer : i)) .
get_next_gensym_counterC(_prefix,_count) :-
gen_symcount(_prefix,_pcount) , ! ,
increment_counter(_count,_pcount) .
get_next_gensym_counterC(_prefix,_count) :-
make_counter(_pcount) ,
assert(gen_symcount(_prefix,_pcount)) ,
_count = 1 .
unfortunately, I had to change the C code as it stands in the tutorial; perhaps
Qprolog is interfacing to some other C ?
long *make_counter()
{
register long *p = (long *)malloc(sizeof *p) ;
*p = 1 ;
return(p) ; /*WAS MISSING IN THE TUTORIAL
this goes right on SUN3 - d0 still contains the return
value of malloc - but on VAX this goes wrong
see also comp.lang.c these days: topic QuickC
*/
}
long increment_counter(p)
register long *p ;
{
(*p)++ ; /*IN THE TUTORIAL VERSION, THIS WAS: *p++ ;
DOING THE SAME AS *(p++) WHICH IS WRONG
*/
return(*p) ;
}
BIMprolog version
-----------------
get_next_gensym_counterB(_prefix,_count) :-
assoc(_prefix,_key) , ! ,
recorded(_key,_old_count) ,
_count is _old_count + 1 ,
rerecord(_key,_count) .
get_next_gensym_counterB(_prefix,_count) :-
make_key(_prefix,_key) ,
assert(assoc(_prefix,_key)) ,
rerecord(_key,1) ,
_count = 1 .
make_key(_prefix,_prefix) . % this could be a more involved predicate, but since
% it is only called once, that's not going to make
% a big difference
Prolog tutorial version
-----------------------
get_next_gensym_counterOK(_prefix,_count) :-
retract(gen_symcount(_prefix,_old_count)) ,
! ,
_count0 is _old_count + 1 ,
assert(gen_symcount(_prefix,_count0)) ,
_count = _count0 .
get_next_gensym_counterOK(_prefix,_count) :-
assert(gen_symcount(_prefix,1)) ,
_count = 1 .
the timings for 10000 calls to get_next_gensym_counter*(a,_x) (on a SUN 3/50)
in seconds:
C OK B
-------------------
5.8 30.4 4.9
(the loop overhead of 0.8 sec was not subtracted)
gensym is clearly a case in which the foreign interface should NOT be used ...
as the BIMprolog manual states: the use of the external interface entails some
overhead, resulting in slower programs when using an external routine for a
short job
in the same section, the tutorial makes the general statement:
'If you need global variables, you might as well implement them in a language
which is good at them.' (meaning not Prolog, I suppose). This is not true.
Prolog has already the record predicates to do that.
bimbart@kulcs.uucp
Bart Demoen
Dept. of Computer Science
Celestijnenlaan 200A
B-3030 Leuven
Belgium
Technical Details
Message-ID:
<1415@kulcs.kulcs.uucp>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!nrl-cmf!ames!amdcad!sun!pitstop!sundc!seismo!uunet!mcvax!prlb2!kulcs!bimbartShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!nrl-cmf!ames!amdcad!sun!pitstop!sundc!seismo!uunet!mcvax!prlb2!kulcs!bimbart From: bimbart@kulcs.uucp (Bart Demoen) Newsgroups: comp.lang.prolog Subject: Seattle tutorial prolog Message-ID: <1415@kulcs.kulcs.uucp> Date: 29 Aug 88 12:42:27 GMT Reply-To: bimbart@kulcs.UUCP (Bart Demoen) Organization: Katholieke Universiteit Leuven, Dept. Computer Science Lines: 114