Subject: Re: [SWIPL] no copy semantics for PlTerm, in the C++ interface

From: Volker Wysk <[email-masked]>
Date: Mon, 5 Nov 2001 03:32:31 +0100 (CET)

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

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
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.

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

Bye