From jan@swi.psy.uva.nl Mon Nov  5 12:04:45 2001
Received: from gollem.swi.psy.uva.nl (root@gollem [145.18.152.30])
	by swi.psy.uva.nl (8.11.2/8.11.2) with ESMTP id fA5B4jt23474;
	Mon, 5 Nov 2001 12:04:45 +0100 (MET)
Received: from localhost (localhost [[UNIX: localhost]])
	by gollem.swi.psy.uva.nl (8.11.3/8.11.3/SuSE Linux 8.11.1-0.5) id fA5B4jf05763;
	Mon, 5 Nov 2001 12:04:45 +0100
From: Jan Wielemaker <jan@swi.psy.uva.nl>
Organization: SWI, University of Amsterdam
To: Volker Wysk <post@volker-wysk.de>
Subject: Re: [SWIPL] no copy semantics for PlTerm, in the C++ interface
Date: Mon, 5 Nov 2001 11:46:18 +0100
X-Mailer: KMail [version 1.0.29.2]
Content-Type: text/plain
Cc: Volker Wysk <post@volker-wysk.de>, <prolog@swi.psy.uva.nl>
References: <Pine.LNX.4.31.0111050238520.2098-100000@volker>
In-Reply-To: <Pine.LNX.4.31.0111050238520.2098-100000@volker>
MIME-Version: 1.0
Message-Id: <01110512044400.05649@gollem>
Content-Transfer-Encoding: 8bit

On Mon, 05 Nov 2001, Volker Wysk wrote:
>On Sun, 4 Nov 2001, Jan Wielemaker wrote:
>
>> > The class PlTerm in the C++ interface, SWI-cpp.h, contains this:
>> >
>> >   int operator =(const PlTerm &t2)	/* term */
>> >   { return PL_unify(ref, t2.ref);
>> >   }
>> >
>> > This is not correct copy semantics. You can't overwrite a PlTerm
>> > object. You can't use PlTerm objects as values like this. For
>> > instance, the Standard Template Library relies on correct copy
>> > semantics. You couldn't store PlTerm's in STL containers, etc.
>> >
>> > I suggest renaming the operator=() methods to unify().
>>
>> I never claimed to be a C++ expert.  = has been redefined to allow
>> natural unification from C++.  I guess you'd like to see
>>
>>    int operator =(const PlTerm &t2)	/* term */
>>    { return PL_put_term(ref, t2.ref);
>>    }
>
>I'm a little confused now. As far as I can tell from the SWI-Prolog
>documentation, we have
>- Terms inside the Prolog machine
>- pointers inside Prolog to terms (= variable bindings?)
>- corresponding term_t values on the C side
>- PlTerm objects

term_t is the same as PlTerm.  term_t is an indirect reference.  It is
the index of a cell on the local stack containing the value (or a
reference to the value, but the C/C++ user doesn't need to be aware
of this.

If you use plain copy of the term_t value, both refer to the same
value-cell.  And thus:

   <x bound to foo(1)> 
   term_t y = x;
   PL_put_atom_chars(y, "hello");
   <both x and y refer to the atom 'hello'>

If you want to see PlTerm objects as holders for a Prolog term writing
to the copy should not affect the original.  SWI-Prolog defines
PL_copy_term_ref(), which createa a new term-reference which points to
the same Prolog term.  Further unification inside this term affects
both, but assignments using PL_put_* affects only the addressed
reference.

>PlTerm objects are lightweight, and it makes perfect sense to use them as
>values (you wouldn't want allocate them on the heap). In order to do this,
>they must behave like values, or unforeseen things will happen. So an
>assignment must make two objects identical. I'm not sure if this is
>completely guaranteed after the PL_put_term() operation.
>
>I'd just do "ref = t2.ref;" instead of the call to PL_put_term. This is
>what the default assignment operator would do. So you could just leave
>away the operator= method.
>
>Also, the return type isn't right; it needs to be PlTerm&. For instance,
>for statements like this: if ((term1 = term2) > term3) { ...
>
>> I think I agree to your proposal, also because = is a bit strange
>> and leads to
>>
>> 	return X = Y;
>>
>> rather then the possibly someway clearer:
>>
>> 	return X.unify(Y);
>>
>> Big problem is that there is a lot of code around that will break
>> if we change this.
>
>I think, the assignment behavior should be changed. The way it is now, it
>can be a great source of errors. It's just too obvious to use PlTerm
>objects as values, like you would use pointers.
>
>There are more things that could be improved. For instance, I found it
>confusing that the indexes of PlTerm::operator[] start at 1, whereas in

This is to stay compatible with Prolog argument counting.  Unclear
whether that is good or bad.

>PlTermv::operator[] they start at 0. I'd abandon the PlTermv class
>altogether, and use vector<PlTerm> instead; or iterators.
>
>I'd also use C++ strings instead of, or in addition to C strings. The
>entire thing could also be better intergreted with the STL. For instance,
>Prolog lists could be mapped to list<>. The conversions from/to PlTerm
>could also be done more elegantly with template methods, or traits. This
>would make it extensible, so you could add your own conversions without
>changing the PlTerm class.

Maybe some C++ experts can make a neat SWI-cpp.h that complies with
STL and uses templates?  My C++ knowledge is too limited.  I can help
with correct implementation though.

>Btw. there's a small bug: PlTerm::functor() (as described in the
>documentation) is PlTerm::name() in SWI-cpp.h.

Thanks.  I'll fix that.

	--- Jan

