Path: 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 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