How do I put an argument in foreign code?

Hello friends,

While implementing the rust wrapper around SWI-Prolog’s foreign language interface, I noticed that while there’s a PL_get_arg() and a PL_unify_arg(), there is no PL_put_arg().

I thought I could just implement PL_put_arg with a combination of PL_get_arg to get a term ref to an argument, and then PL_put_* into that term ref, as in the pseudocode below.

functor_term = PL_new_term_ref();
PL_put_term(functor_term, some_functor);
term = PL_new_term_ref();
PL_get_arg(1, functor_term, term);
PL_put_bool(term, false);

But this does not appear to affect the term referenced by functor_term at all. the first arg remains a variable. Or if there’s something already in that position, it remains whatever was there.

So how should I actually do this?


You cannot put on a term, only on a term reference. In the example, you first make term point at the 1st argument of the compound and then you set it to false. No Prolog data is affected by either of these actions. You can unify to the nth argument of a compound, which is the same as arg/3. Are you trying to get the same effect as (nb_) setarg/3? This functionality is currently not provided by the foreign API (except for making a call to Prolog).

It wouldn’t be hard to provide. I’m not really against this, although I am a little concerned that people might misuse such features a little too easily :slight_smile:

To clarity, given c bound to f(_), this works:

term_t a = PL_new_term_ref();
PL_put_bool(a, false);
PL_unify_arg(1, c, a);

A foreign setarg/3 would be nice, as would nb_setarg/3. I’d definitely misuse the heck out of it.

But for now, I’ll just use unification for args instead. Thanks for clarifying!

1 Like