Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to write a predicate with the PREDICATE macro that supports multiple bindings for one variable? #4

Open
airballking opened this issue Jan 25, 2018 · 9 comments

Comments

@airballking
Copy link

I have a beginner question about the SWI-Prolog C++ interface. If this is the wrong place to post such a question, I apologize and ask: Where should I ask such a question?

I want to create a predicate foo_bar/1 that binds two possible solutions to its variable. Meaning, I want the following behavior of the resulting call in prolog:

?- foo_bar(X).
X = foo ;
X = bar.

In Prolog, I'd implement it like this:

foo_bar(X) :-
  X = foo;
  X = bar.

Now, I'd like to implement the same behavior using the C++ interface. I tried this:

PREDICATE(foo_bar, 1) {
    PL_A1 = std::string("foo").c_str();
    PL_A1 = std::string("bar").c_str();
    return true;
}

But it only returns the first binding:

?- foo(X).
X = foo.

Does the C++ interface support implementing this type of predicate? If yes, how can I do it?

Thank you very much in advance for your support!

@wouterbeek
Copy link

I learned how to write these by looking at some examples, e.g., the following predicate by Jan is non-deterministic: https://github.com/JanWielemaker/hdt/blob/e0a0eff87fc3318434cb493690c570e1255ed30e/c/hdt4pl.cpp#L363

@vmatare
Copy link
Contributor

vmatare commented Jan 25, 2018

Seems like it's not explicitly supported by the C++ binding. But since it's just a wrapper around the C foreign language interface, you can just use that.

@airballking
Copy link
Author

@wouterbeek and @vmatare thank you for the quick and insightful reponses! The combined information on both linked pages gave me an idea of how to implement such a predicate.

However, when I started implementing my predicate, the compiler very quickly complained about an invalid type cast in the SWI-PL infrastructure. Here is a minimal version of what I tried that still produces the error:

PREDICATE_NONDET(foo_bar, 1) {
    switch( PL_foreign_control(handle) ) {}
}

Here is the error that I got:

error: invalid conversion from ‘foreign_t {aka long unsigned int}’ to ‘control_t {aka void*}’ [-fpermissive]
     switch( PL_foreign_control(handle) ) {
                                      ^
In file included from /usr/lib/swi-prolog/include/SWI-cpp.h:27:0,
                 from /home/georg/ros/knowrob/src/knowrob/rosprolog/include/rosprolog.h:8,
                 from /home/georg/ros/knowrob/src/knowrob/knowrob_srdl/src/urdf_parsing.cpp:1:
/usr/lib/swi-prolog/include/SWI-Prolog.h:274:17: note:   initializing argument 1 of ‘int PL_foreign_control(control_t)’
 PL_EXPORT(int)  PL_foreign_control(control_t);

It seems that the variable handle, as provided by PREDICATE_NONDET, is not of a type directly compatible with what PL_foreign_control() expects.

Do you see any obvious mistake I made? Or, do you have an idea how to fix this?

@wouterbeek
Copy link

I don't understand your error, line 27 in my SWI-cpp.h file falls within a multi-line comment.

@airballking
Copy link
Author

I read this hint as: At line 274 of SWI-Prolog.h, which is included from SWI-cpp.h at line 27, which is included from ..., you can find the definition of the failing PL_foreign_control(control_t).

@JanWielemaker
Copy link
Member

But, indeed line 27 is in a comment, so you probably have an old version. At least use version
7.6.x

@airballking
Copy link
Author

Ah, I see. Sorry for the confusion. I am using SWI-Prolog from deb packages on ROS 16.04. apt-cache says that is version 7.2.3-2. I'll try installing a newer version.

@wouterbeek
Copy link

@airballking The Linux packages are very outdated, unfortunately. Luckily, SWI-Prolog is very easy to compile on Linux. The Debian-specific instructions are documented here: http://www.swi-prolog.org/build/Debian.html

@airballking
Copy link
Author

@wouterbeek thank you for the link!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants