A long time ago I would embed SWI-Prolog in my application. Since then I decided that it’s a much superior approach to use a client/server architecture with a TCP connection. This gives the flexibility to run SWI developer UI when I want to do that. It takes a bit of coding effort to create and manage such a link but I like the flexibility that comes when you have it. (And I’m using C# client side.)
Interesting. Would you use the client/server architecture even on the same machine? I read that marshaling data between C# and C++ causes a slight delay–but I thought it would be much faster than TCP, no?
That’s the idea behind wafe - despite the description, it’s more general than just X11 clients. (I have some sample code for javascript→Prolog; the client could be easily modified to use a different language.)
That’s how Google does almost everything, and they care a lot about efficiency. For marshaling data, they uses protobufs which (at least in C++) are more efficient than JSON, and also quite compact. (I think that modern implementations of TCP on Linux and Unix-like systems short-circuit TCP connections when they’re on the same machine.)
My javascript→Prolog code could be easily modified to use protobufs instead of JSON.
@peter.ludemann & @abaljeu , could I use this approach for a mobile app sold on Google Play or the iOS Store? I had assumed I would embed a version of Prolog in the app itself and ship a single file. Perhaps this topic should be in its own thread?
Yes, this should be a separate thread and no, I don’t know how to set up a SWI-Prolog server on Android or IOS.
(Or Windows, for that matter, although thanks to Jan’s work, I presume that it mostly JustWorks.)
@peter.ludemann & @abaljeu , I appreciate this advice. I’ll work to embed the DLL first, since that is what I sort of understand. I’ll return to the embedding versus client/server debate later. This low-level architecture thing is not my cup of tea. If I don’t get back to writing logic and content soon, I’ll probably burn out before this project is complete!
For Android, you could presumably use JNI to embed Prolog.
On iOS, since it’s C, and Objective-C is a strict superset, you could theoretically include it directly. However, there used to be rules about embedding interpreters and the ToS only allowed Javascript; I’m not sure if that’s still the case/enforced though.
Very long time ago I needed to argue the program in C as SWI-Prolog is in C and the rest is just data, no? ![]()
@jan , I’m finally ready to get back to the original question! Swish may eventually be more convenient, but I immediately received syntax and other errors and feel more comfortable (for now) debugging in my own editor. All the examples below start with :- use_module(library(scasp)). and end with the rule scared(P) :- -escape(P), faces_conflict(P), is_weaker(P).
Let’s start with the simplest case.
-escape(john).
faces_conflict(john).
is_weaker(john).
John has no escape, faces a conflict, and is the weaker party. Is he scared? You bet he is! Querying ? scared(john). reproduces the rule in grounded form, neatly printed.
In the next situation, John has an escape:
escape(john).
faces_conflict(john).
is_weaker(john).
My editor (Visual Studio Code with Arthur Wang’s VSC-Prolog extension) warns me that “Predicate ‘-escape’/1 not defined”, but the program runs fine. Is he scared? Nope.
?- ? scared(john).
false.
Why isn’t he scared?
?- ? -scared(john).
ERROR: scasp_predicate `'-user:scared'/1' does not exist
ERROR: In:
ERROR: [26] throw(error(existence_error(scasp_predicate,...),_984))
ERROR: [23] apply:maplist_(['-user:scared'(john),o_nmr_check],scasp_compile:check_existence('tmp-1-3752469445171599962')) at c:/program files/swipl/library/apply.pl:225
ERROR: [20] scasp_embed:scasp_call('tmp-1-3752469445171599962':'-user:scared'(john)) at c:/users/dvyd/appdata/local/swi-prolog/pack/scasp/prolog/scasp/embed.pl:313
ERROR: [19] scasp_dyncall:scasp_call_and_results('tmp-1-3752469445171599962':'-user:scared'(john),user,[]) at c:/users/dvyd/appdata/local/swi-prolog/pack/scasp/prolog/scasp/dyncall.pl:125
ERROR: [17] setup_call_catcher_cleanup(modules:prepare_temporary_module('tmp-1-3752469445171599962'),modules:(... -> ...),_1160,modules:destroy_module('tmp-1-3752469445171599962')) at c:/program files/swipl/boot/init.pl:663
ERROR: [12] setup_call_catcher_cleanup(scasp:set_prolog_flag(scasp_show_justification,false),scasp:scasp(...),_1222,scasp:set_prolog_flag(scasp_show_justification,unicode)) at c:/program files/swipl/boot/init.pl:663
ERROR: [9] toplevel_call('<garbage_collected>') at c:/program files/swipl/boot/toplevel.pl:1162
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
Call: (19) modules:destroy_module('tmp-1-3752469445171599962') ? creep
^ Call: (20) retractall(system:'$load_context_module'(_14894, 'tmp-1-3752469445171599962', _14898)) ? creep
What did I do wrong?
s(CASP) has two notions of negation: classical negation where you tell the system what is known to be false and negation-as-failure (NAF) where the system cannot prove something is true and therefore assumes it is false. The first is written as -term and the latter as not term. Note that the classical negated world is pretty much disjoint from the positive world. Only, the system rejects any model that both contains X and -X.
You’re trying -scared(john), but as there are no rules for this it has no way to prove this. Try ? not scared(john)., i.e. “why can’t I prove scared(john) is true?”
s(CASP) requires quite a different mindset than Prolog ![]()
See SWISH -- SWI-Prolog for SHaring

Thanks @jan . not -escape(john) is the answer I was looking for, but I can’t seem to get to it from the desktop interpreter. How do I get the justification, from scasp/2? What is the synax? The question mark just gives me the model, right?
?- ? not scared(john).
% s(CASP) model
{ not scared(john)
} .
use
?? not scared(john).
The web version gives both, but can use folding of the model and justification.
Something like this. I don’t have the exact details handy now. I do not send general Prolog queries though. I send a Prolog term in text form that’s pattern-matched and an action determined from there.
