BinProlog compatibility layer?

Looks that SWI-Prolog has a BIM-Prolog compatibility layer. According to a 1993 user manual it had change_arg/4, but I don’t find it here.

This file contains some predicates that are defined in BIM-prolog and not in SWI-prolog
https://www.swi-prolog.org/pldoc/doc/SWI/library/dialect/bim.pl

But I am looking for an other Prolog compatibility layer, namely BinProlog and not BIM-Prolog. This had change_arg/3, a predicate I am currious about.

change_arg/3 seems to be the same as nb_setarg/3 except that the documentation talks about “unsafe heap operations”. No such thing exists for SWI-Prolog. There is also nb_linkarg/3. That is more low-level and might be about the “unsafe heap operations”. I don’t know.

The compatibility layers are typically developed along with projects and therefore pretty incomplete. Ideally the next project extend on it and in the end you get something workable. A full compatibility layers that emulates all dark corners of some other system is a lot of work!

On my timing I get an about 10% performance loss for your findall2/3 (both on Linux and Windows). The fun thing is that the timings changed quite a bit. When I added nb_setarg/3 I wrote a version of findall/3 based on it, but it was so much slower that I decided to keep the old one. My version seems slightly more efficient and now hits only a 3% loss. That might make it worthwhile due to its simplicity and the smaller overhead for findall calls that produce few solutions. Here is also one that does not copy if there is only one answer:

find_few2(T, G, L) :-
	L0 = [dummy|_],
	Result = list(L0),
	(   call_det(G, Det),
	    (	Det == true,
		arg(1, Result, L1),
		L0 == L1
	    ->	!, L = [T]
	    ;	duplicate_term(T, T2),
		NewLastCell = [T2|_],
		arg(1, Result, LastCell),
		nb_linkarg(2, LastCell, NewLastCell),
		nb_linkarg(1, Result, NewLastCell),
		fail
	    )
	;   arg(1, Result, [_]),
	    L0 = [_|L]
	).

call_det(G, Det) :-
	call(G),
	deterministic(Det).

Well, on my measurements my version is faster than yours. Of course that depends on the platform. This version was developed in a project that used findall/3 in a scenario where there is frequently only one answer. That is why is is called “find_few” :slight_smile: The call_det/2 hack avoids the need to copy anything if there is only one answer. The drawback is that you get the copy semantics for non-det goals and the non-copy semantics for (semi)det goals. That was not a problem for this project, but in general it is not acceptable.

That we have now an acceptable performance difference is probably due to better compilation of arg/3, and inline unification. Well, the lesson is that this design is now viable. Given how much simpler it is that the actual implementation of findall/3 makes reconsidering a real option. There is nothing wrong with how it is implemented now though, so there is hurry.

Works fine for any atomic data. The set and link variants only differ for compound terms. I see it still call duplicate_term, but this is a no-op for atomic data. Enhanced to avoid this.