# Unable to retract/retractall using c interface

**URL:** <https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025>\
**Category:** Help!\
**Created:** [August 2, 2019, 11:17am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025 "2019-08-02T11:17:26Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 2, 2019, 11:17am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/1 "2019-08-02T11:17:26Z")

</div>

I’m using: SWI-Prolog version 8.0.2  
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

I want the code to:  
retract asserted facts.  
i’ve tested predicates defined with both the dynamic and thread\_local definitions ( same results )

i’ve tested both retractall on a compound built with PL\_put\_variable (i.e. retractall(functor(_,_,…)  
-\> **next\_solution returns PL\_S\_TRUE but does not retract** ( subsequent “selection” of the data returns data ).

i’ve tried implementing my own retractall ( i.e. read all values/solutions and explicitly retract each one )  
**but next\_solution on the retract returns PS\_S\_FALSE.** ( and does not retract the data ).

code examples :

**using retractall :**  
const predicate\_t RetractCMD = PL\_predicate(“retractall”, 1, “database”);  
const functor\_t Targetfunctor = PL\_new\_functor(PL\_new\_atom(“target”), 4);  
term\_t EmptyTargetParameters = PL\_new\_term\_refs(4);  
if ( PL\_put\_variable(EmptyTargetParameters) != PL\_S\_TRUE  
|| PL\_put\_variable(EmptyTargetParameters+1) != PL\_S\_TRUE  
|| PL\_put\_variable(EmptyTargetParameters+2) != PL\_S\_TRUE  
|| PL\_put\_variable(EmptyTargetParameters+3) != PL\_S\_TRUE)  
{ exit }

term\_t TargetCompoundToRetract = PL\_new\_term\_ref();  
if (PL\_cons\_functor\_v(TargetCompoundToRetract,Targetfunctor,EmptyTargetParameters) != PL\_S\_TRUE)  
{ exit }

const qid\_t RetractTargetsQID = PL\_open\_query(NULL, PL\_Q\_NODEBUG ,RetractCMD,TargetCompoundToRetract);  
if (RetractTargetsQID == 0)  
{ exit }

QueryRc = PL\_next\_solution(RetractTargetsQID);  
if (QueryRc != PL\_S\_TRUE)  
{ exit }

**using retract :**  
const predicate\_t PredToDelete = PL\_predicate(“target”, 4, “database”);  
term\_t DataToDelete = PL\_new\_term\_refs(4);  
const functor\_t functorToDelete = PL\_new\_functor(PL\_new\_atom(“target”), 4);  
const predicate\_t RetractCMD = PL\_predicate(“retract”, 1, “database”);

const qid\_t GetDataQID = PL\_open\_query(NULL,PL\_Q\_NODEBUG,PredToDelete,DataToDelete);  
if (GetDataQID == 0)  
{ exit }

```
int QueryRc = PL_next_solution(GetDataQID);
while (QueryRc != PL_S_FALSE)
{
     // construct compound argument for retract command
    term_t CompoundToRetract = PL_new_term_ref();
    if (PL_cons_functor_v(CompoundToRetract,functorToDelete,DataToDelete) != PL_S_TRUE)
    { exit }

  const qid_t RetractQID = 
  PL_open_query(NULL,PL_Q_NODEBUG,RetractCMD,CompoundToRetract);
    if (RetractQID == 0)
    { exit }   

   //
    QueryRc = PL_next_solution(RetractQID);
    if (QueryRc != PL_S_TRUE)
    { exit }

}
```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 2, 2019, 11:38am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/2 "2019-08-02T11:38:57Z")

</div>

Without looking through all details, I _think_ the misconception is with `PL_predicate(“retractall”, 1, “database”)`. This doesn’t get retractall/1 for the module `database`, but the meta predicate retractall/1 as it is visible in `database`, which is the same as in `system` or any other module.

Next, you call it without module context and this means you’re probably referring to the `system` module. The debugger should be able to tell you.

You should either create a term `database:target(_,_,_,_)` or pass the module `database` as first argument to `PL_open_query()`.

P.s. `PL_S_TRUE` and friends are for the extended return status of `PL_next_solution()` only. All other functions return 1 or 0, available as `TRUE` and FALSE`.

And as a general remark. keep the stuff you call from C(++) as simple as possible. For example, define in `database` a predicate `cleanup/0`. That also fixes the module stuff:

```prolog
cleanup :-
    retractall(target(_,_,_,_)).

```

---

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 4, 2019, 10:03am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/3 "2019-08-04T10:03:07Z")

</div>

thank you Jan for trying to help.

I was not aware of the “modules” element.  
(as far as i can tell its not the cause (all my assert/retract statements use the “database” module) )

I’ve done some debugging.  
it looks like some sort of bug in the assert of compound predicates.

I have more then 1 predicate i need to assert/retract.  
my code works for one predicate with only 1 parameter.

but once i add the assert(target(int,int,int,int)) it messes things up , it even messed up the “state” of the other predicate ( the one that has only 1 int parameter).

i’ve debugged it to the point that i can say that the following cmd is the one that causes the problem :  
if (!PL\_put\_integer(TargetToAssert+3,int))  
i.e. setting the value in the last element of the array ( used later in PL\_cons\_functor\_v).

any ideas?

omer.

---

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 4, 2019, 11:51am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/4 "2019-08-04T11:51:30Z")

</div>

btw,

i’ve tried the “cleanup” workaround.  
but it did not work.

i’ve defined :  
cleanup(NewMaxCostFound):-  
retractall(target(_,_,_,_)),  
retractall(maxcostfound(\_)),  
assert(maxcostfound(NewMaxCostFound)).

count\_number\_of\_asserted\_targets(NumberOfTargets):-  
findall(TargetID,target(TargetID,_,_,\_),Bag),  
length(Bag,NumberOfTargets).

a new cpp method that calls cleanup .  
then asserts one “target”  
then calls count\_number\_of\_asserted\_targets.

on its first execution (nothing to retract) i get the correct number of targets (=1)  
second execution of the same code , i get number of asserted targets = 0.

?  
Omer

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 5, 2019, 7:40am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/5 "2019-08-05T07:40:47Z")

</div>

> [@OmerBrandis](#):
>
> it looks like some sort of bug in the assert of compound predicates.

Nothing is impossible, but I consider that highly unlikely. Most likely you are misusing the C++ API somehow. As there is no complete code it is hard to say where though. If Prolog has access to the console you can insert a trace/0 call to see what is called. Misuse of the C++ API can easily result in data corruption and crashes though. One trick is to call garbage\_collect/0, as this normally either crashes or make slightly wrong data completely wrong.

---

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 5, 2019, 11:52am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/6 "2019-08-05T11:52:16Z")

</div>

hello Jan,

would you like me to post the complete code here?

thanks,  
Omer

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 5, 2019, 12:05pm UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/7 "2019-08-05T12:05:37Z")

</div>

Preferably something small, but complete so we can compile and run it. If it can’t be small (but it seems it can), put it somewhere else and point us at the things we should look at.

---

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 6, 2019, 10:27am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/8 "2019-08-06T10:27:07Z")

</div>

hello Jan,

here is a slightly watered down version of the code

void InitQuery()  
{

```
term_t MaxCostFoundTerm = PL_new_term_ref();
if (!PL_put_integer(MaxCostFoundTerm,MaxCostFound))
{
    return;
}

const predicate_t InitWingCMD = PL_predicate("initialize_wing_path_query",1,"database");
const qid_t InitWingPathQID = PL_open_query(NULL, PL_Q_NORMAL,InitWingCMD,MaxCostFoundTerm);
if (InitWingPathQID == 0)
{
    return;
}

QueryRc = PL_next_solution(InitWingPathQID);
//std::cout << "qrc = " << QueryRc << std::endl;
if (QueryRc != TRUE)
{
    return;
}

if (!PL_close_query(InitWingPathQID))
{
    return;
}

	// assert target //

//
if (!PL_put_integer(TargetToAssert,1))
{
    return;
}
if (!PL_put_integer(TargetToAssert+1,2))
{
    return;
}
if (!PL_put_integer(TargetToAssert+2,3))
{
    return;
}

if (!PL_put_integer(TargetToAssert+3,4))
{
    return;
}
 
//
const functor_t Targetfunctor = PL_new_functor(PL_new_atom("target"), 4);
const predicate_t AssertCMD1 = PL_predicate("assert", 1, "database");
term_t TargetCompoundToAssert = PL_new_term_ref();
if (!PL_cons_functor_v(TargetCompoundToAssert,Targetfunctor,TargetToAssert))
{
    return;
}
 
//
const qid_t AssertTargetQID1 = PL_open_query(NULL, PL_Q_NORMAL,AssertCMD1,TargetCompoundToAssert);
if (AssertTargetQID1 == 0)
{
    return;
}

QueryRc = PL_next_solution(AssertTargetQID1);
if (QueryRc != TRUE)
{
    return;
}

if (!PL_close_query(AssertTargetQID1))
{
    return;
}

```

}

void CheckInitQuery()  
{  
std::cout \<\< "check assertion of max cost found " \<\< std::endl;

```
    // check assertion of max cost found //
          term_t Result = PL_new_term_ref();
    const predicate_t PredToRun = PL_predicate("maxcostfound", 1, "database");
    const qid_t QID = PL_open_query(NULL,PL_Q_NODEBUG | PL_Q_EXT_STATUS,PredToRun,Result);
    if (QID == 0)
    {
        return;
    }

    QueryRc = PL_next_solution(QID);
    //std::cout << "qrc = " << QueryRc << std::endl;
    if (QueryRc != PL_S_LAST)
    {
        return;
    }

    // parse the result
    //std::cout << "term type " << PL_term_type(Result) << std::endl;
    if (PL_term_type(Result) != PL_INTEGER)
    {
        return;
    }

    int ReadInt;
    if (PL_get_integer(Result,&ReadInt) != PL_S_TRUE)
    {
        return;
    }
    if (ReadInt != MaxCostFound)
    {
        return;
    }
    std::cout << "max cost found asserted successfully" << std::endl;

    if (!PL_close_query(QID))
    {
        return;
    }

    // check number of asserted targets //
          term_t NumberOfAssertedTargets = PL_new_term_ref();
    const predicate_t CountCMD = PL_predicate("count_number_of_asserted_targets", 1, "database");
    const qid_t CountQID = PL_open_query(NULL,PL_Q_NODEBUG,CountCMD,NumberOfAssertedTargets);
    if (CountQID == 0)
    {
          return;
    }

    QueryRc = PL_next_solution(CountQID);
    //std::cout << "qrc = " << QueryRc << std::endl;
    if (QueryRc != TRUE)
    {
        return;
    }

    // parse the result
    if (PL_term_type(NumberOfAssertedTargets) != PL_INTEGER)
    {
        return;
    }

    if (PL_get_integer(NumberOfAssertedTargets,&ReadInt) != PL_S_TRUE)
    {
        return;
    }

    std::cout << "number of targets asserted = " << ReadInt << std::endl;

    if (!PL_close_query(CountQID))
    {
        return;
    }

```

}

i’ve already posted the contents of count\_number\_of\_asserted\_targets and initialize\_wing\_path\_query.

my prolog src file also contains:  
:- thread\_local target/4.  
:- thread\_local maxcostfound/1.

Thanks,  
Omer.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 6, 2019, 10:52am UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/9 "2019-08-06T10:52:03Z")

</div>

So sorry, but it is incomplete. `TargetToAssert` is declared nor initialized. Same for several other variables. There are no included headers, there is no `main()` or some other indication how it is loaded and started. The stuff that is there seems to make sense, but essential stuff is missing and if it turns out there is nothing obviously wrong someone who wants to help you will have to complete the code such that it can be compiled and executed.

Please send \__complete_ code and do not ask the list to collect and fill out the blanks.

---

<div class="post-metadata">

**Author:** ![OmerBrandis](https://avatars.discourse-cdn.com/v4/letter/o/f1d935/32.png) [@OmerBrandis](https://swi-prolog.discourse.group/u/OmerBrandis)\
**Post date:** [August 6, 2019, 12:08pm UTC](https://swi-prolog.discourse.group/t/unable-to-retract-retractall-using-c-interface/1025/10 "2019-08-06T12:08:42Z")

</div>

Ok Jan,  
u r correct 100%,

i’ve polished off the watered down version,  
and found out it works correctly.

so i’ll keep digging.

thanks again for all the help.  
Omer.
