0

When you execute anything in prolog you can see that the result of the evaluation comes out as:

true

or

false

I would like to change those values for personalized ones.

Based on this question, I saw that what I want is defined in the messages.pl file

where I found that they are defined as:

query_result(no) -->            % failure
    [ ansi(truth(false), 'false.', []) ],
    extra_line.
query_result(yes(true, [])) -->      % prompt_alternatives_on: groundness
    !,
    [ ansi(truth(true), 'true.', []) ],
    extra_line.

I'd like that instead of getting false or true, I could get <ERROR::> and <PASSED::> respectively for my unit tests.

Additional info

I am doing the unit test to a file called adition.pl consisting solely of.

 my_add(A,B,Result):- number(A), number(B), is(Result,+(A,B)). 

Attempt

:-['C:/Users/RuslanLopez/Documents/Prolog/adittion.pl'].
%:-['C:/Program Files/swipl/boot/messages.pl'].
:- begin_tests(my_add).
:- include(adittion).
%:- use_module($messages).
%:- include(messages).
error:-write('<ERROR::>'),nl.
passed:-write('<PASSED::>'),nl.

:- dynamic(user:query_result/1).

user:query_result(no) -->            % failure
        [ ansi(truth(false),'<ERROR::>', []) ].

user:query_result(yes(true, [])) -->      % prompt_alternatives_on: groundness
        !,
        [ ansi(truth(true),'<PASSED::>' , []) ].




test(my_add):-
        my_add(1,2,Result),
        Result =:= 3.

test(my_add) :-
        my_add(1,2,Result),
        Result \= 4.

:- end_tests(my_add).

I understand that the more straightforward solution would be to go to the file and change the value directly there, but I really wish I could make the change at runtime to change that custom behavior only in my unit test and not for the entire system.

false
  • 10,264
  • 13
  • 101
  • 209
Ruslan López
  • 4,433
  • 2
  • 26
  • 37
  • 1
    Couldn't you just [`call/1`](https://www.swi-prolog.org/pldoc/doc_for?object=call/1) the predicate to test and print accordingly based on success or failure? (Further, have you taken a look at [Prolog Unit Tests](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/plunit.html%27)) – David Tonhofer Jan 02 '20 at 10:05
  • @DavidTonhofer yes, however, it will print true or false in the console, that's what I want to silence without creating a repl. – Ruslan López Jan 03 '20 at 04:31
  • The idea seems to be to modify the presentation to the user, who is working in the interpreter's REPL instead of a bespoke REPL. That requirement seems needlessly byzantine and "wedged"? – David Tonhofer Jan 03 '20 at 09:12
  • @DavidTonhofer I will not be calling it from the interpreters repl It's to be run inside a docker container. In this way it could be possible to add programming excercises to the codewars.com site – Ruslan López Jan 03 '20 at 14:07
  • Would it be possible to start a Prolog process and perform query/response exchange using PLTP ("Prolog Transport Protocol") as described here: [Pengines: Web Logic Programming Made Easy](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/pengines.html%27)) – David Tonhofer Jan 04 '20 at 08:30
  • @DavidTonhofer but I don't want it to be interactive – Ruslan López Jan 04 '20 at 19:05
  • Well, it should be like a JDBC or ODBC call to an SQL database, right? You don't want to change the prompt of the SQL database client program, you just want to issue a query from *your* program, get the rowset in return, and process it in whichever way you want. It's the same. – David Tonhofer Jan 04 '20 at 19:44
  • @DavidTonhofer it's actually like the SQL query terminator `;` was always added and I want to remove it, and I want to do it without modifying the library that adds such terminator. – Ruslan López Jan 04 '20 at 23:41

2 Answers2

3

Don't. You want to change a very central part of a Prolog system, namely the toplevel (loop). But you will need this toplevel to interactively diagnose and debug your program. Any change to the toplevel will be visible in that context too. The toplevel is the result of many decades of Prolog use by various user groups. It contains much more than the response true and false. Just try X = 1, or even X = s(s(X)), or dif(X,2).

plunit is a unit testing package availabe for SWI, SICStus and some further systems. Use this instead, or roll our own, based on inspired by it.

false
  • 10,264
  • 13
  • 101
  • 209
  • So, are you saying that is not possible to redefine a system predicate on the fly? ( Context of my question https://github.com/Codewars/codewars-runner-cli/issues/159 ) – Ruslan López Jan 03 '20 at 04:42
  • 1
    Redefining system predicates is virtually never a good idea. (Exception maybe, if you want to correct an incorrect definition. But otherwise, never). – false Jan 03 '20 at 11:29
  • so it's possible? – Ruslan López Jan 03 '20 at 14:06
  • 1
    Please read the manual. What you are asking in your original question is not possible that way. You have to change the source code to obtain that. Good luck. – false Jan 03 '20 at 14:50
1

The toplevel is just a predicate prolog/0 that is run when the Prolog interpreter is started. Command line options allow running another predicate or then you need to modified the existing is code, if you want a different toplevel by default.

I got an open source top-level in my Prolog system fully written in Prolog itself. It can also show solved constraints. Its open source here:

Open Source: Module "session"
runtime/session.p

The true and false values are internationalized through property files. So in German you see "Ja" and "Nein", and in English you see "Yes" and "No". Since internationalization API is not really standardized you find some custom built-in calls.

A properties file needs to be preloaded via this statement here:

:- sys_load_resource(runtime).

And a value for a key, depending on current language settings, is then retrieve via such a code sequence:

sys_show_assoc([], _) :-
   get_properties(runtime, P),
   get_property(P, 'query.yes', V),
   write(V).