Installation
Prompt
How to install SWI-Prolog on Windows
ChatGPT Completion
To install SWI-Prolog on Windows, follow these steps:
- Download the SWI-Prolog installation file for Windows from the official website (SWI-Prolog downloads)
- Double-click on the installation file to start the setup process.
- Follow the on-screen instructions to complete the installation.
- Add the SWI-Prolog bin folder to the PATH environment variable to make it accessible from the command line.
- Example: If you installed SWI-Prolog in C:\Program Files\swipl, add C:\Program Files\swipl\bin to your PATH environment variable.
You can now start the SWI-Prolog interpreter by opening the Command Prompt and typing swipl.
If you search for how to install SWI-Prolog on Windows you may find some YouTube videos, using winget and other sets of instructions. The official place to find the SWI-Prolog download for the installer on Windows is correctly given by ChatGPT, SWI-Prolog downloads.
For more detailed instructions with screen shots of steps see:
Install SWI-Prolog development version on Windows 10
Constraints - Finite Domain
Prompt
Create SWI-Prolog Prolog code to solve the 8 queens problem using finite domain constraints.
ChatGPT Completion
Here is an example SWI-Prolog code that solves the 8 queens problem using finite domain constraints:
:- use_module(library(clpfd)).
% This predicate finds a solution to the 8 queens problem and prints it.
queens :-
% Define the domain of the variables.
length(Queens, 8),
Queens ins 1..8,
% Define the constraints.
all_different(Queens),
diagonal_constraints(Queens),
% Use labeling to find a solution.
labeling([], Queens),
% Print the solution.
print_solution(Queens).
% This predicate defines the diagonal constraints.
diagonal_constraints([]).
diagonal_constraints([Q|Queens]) :-
diagonal_constraints(Queens, Q, 1),
diagonal_constraints(Queens).
diagonal_constraints([], _, _).
diagonal_constraints([Q|Queens], Q0, D0) :-
D is abs(Q0 - Q),
D \= D0,
D1 is D0 + 1,
diagonal_constraints(Queens, Q0, D1).
% This predicate prints a solution to the 8 queens problem.
print_solution([]).
print_solution([Q|Queens]) :-
print_row(Q),
print_solution(Queens).
print_row(Q) :-
Length is 8 - Q,
write('|'),
print_spaces(Length),
write('Q'),
print_spaces(Q - 1),
write('|'),
nl.
print_spaces(0).
print_spaces(N) :-
write(' '),
N1 is N - 1,
print_spaces(N1).
To use this code, simply load it into SWI-Prolog and call the
queens
predicate:
?- queens.
| Q|
|Q 8 |
| Q 6 |
| Q 1 |
| Q 5 |
| Q 3|
| Q 2|
| Q7|
true .
This will find a solution to the 8 queens problem and print it. The solution will consist of a list of 8 integers, each representing the row of the queen in the corresponding column. The output is formatted to display the board with the queen positions using ASCII characters.
The code does not result in any warnings or errors with make/0 on SWI-Prolog, it does result in an error when run.
?- queens.
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [13] _27268 is abs(_27278-_27280)
For the more general problem of queens on a square board see:
clpfd - Understanding CLP(FD) Prolog code of N-queens problem - Stack Overflow
Data conversion to/from JSON
In programming, you often need to convert data to or from other formats for use with other software. One of the most common formats for interchanging data is JSON. One of the easiest ways to get ChatGPT to work with a table of data is to have it generate a small set of data and instruct it to limit the size, often by specifying a number.
Prompt
Generate data about the first 10 U.S. presidents as Prolog facts.
% Facts about the first 10 U.S. Presidents
president(1, george_washington, 1789, 1797).
president(2, john_adams, 1797, 1801).
president(3, thomas_jefferson, 1801, 1809).
president(4, james_madison, 1809, 1817).
president(5, james_monroe, 1817, 1825).
president(6, john_q_adams, 1825, 1829).
president(7, andrew_jackson, 1829, 1837).
president(8, martin_van_buren, 1837, 1841).
president(9, william_henry_harrison, 1841).
president(10, john_tyler, 1841, 1845).
Prompt
For SWI-Prolog create a Prolog predicate to convert president data to JSON. Use SWI-Prolog libraries as needed.
ChatGPT Completion
Here is a Prolog predicate that converts the Prolog facts about the first 10 U.S. presidents to JSON using the SWI-Prolog libraries:
:- use_module(library(http/json)).
presidents_json(PresidentsJson) :-
findall(President, president(President), Presidents),
maplist(president_json, Presidents, PresidentsJsonList),
dict_create(PresidentsDict, presidents, PresidentsJsonList),
json_write_dict(current_output, PresidentsDict, [indent(2)]).
president_json(president(Number, Name, StartYear, EndYear), PresidentJson) :-
dict_create(PresidentDict, president, [
number-Number,
name-Name,
start_year-StartYear,
end_year-EndYear
]),
PresidentJson = PresidentDict.
The
presidents_json/1
predicate takes one argument,PresidentsJson
, which is the JSON representation of the first 10 U.S. presidents. The predicate uses thefindall/3
built-in predicate to gather a list of all thepresident
facts, then maps over that list using thepresident_json/2
predicate to convert each fact to a JSON object. Finally, thedict_create/3
predicate is used to create a dictionary with the list of JSON objects, which is then written to the current output as formatted JSON using thejson_write_dict/3
predicate.The
president_json/2
predicate takes apresident/4
fact and converts it to a JSON object. It uses thedict_create/3
predicate to create a dictionary with the relevant fields for the president, then creates a new dictionary with thepresident
key and the dictionary of fields. This new dictionary is then unified with thePresidentJson
argument.
The code results in a warning with make/0 on SWI-Prolog.
Warning: Singleton variables: [PresidentsJson]
It results in an error when run.
?- presidents_json(_).
ERROR: Type error: `key-value' expected, found `president{end_year:1797,name:george_washington,number:1,start_year:1789}' (a dict)
Here is correct code.
presidents_json :-
findall(president(Number, Name, StartYear, EndYear), president(Number, Name, StartYear, EndYear), Presidents),
maplist(president_json, Presidents, PresidentsJsonList),
dict_create(PresidentsDict, presidents, PresidentsJsonList),
json_write_dict(current_output, PresidentsDict, [indent(2)]).
president_json(president(Number, Name, StartYear, EndYear), Name-PresidentDict) :-
dict_create(PresidentDict, president, [
number-Number,
name-Name,
start_year-StartYear,
end_year-EndYear
]).
The first change is make the Goal and Template arguments for finall/3 the same,
findall(president(Number, Name, StartYear, EndYear), president(Number, Name, StartYear, EndYear), Presidents)
The second change is to change the result of president_json/2 to return a key-value instead of a dict.
The third change is to just remove the argument for presidents_json/1 as it is not used.
Example run of corrected code on SWI-Prolog.
?- example:presidents_json.
{
"andrew_jackson": {
"end_year":1837,
"name":"andrew_jackson",
"number":7,
"start_year":1829
},
"george_washington": {
"end_year":1797,
"name":"george_washington",
"number":1,
"start_year":1789
},
"james_madison": {
"end_year":1817,
"name":"james_madison",
"number":4,
"start_year":1809
},
"james_monroe": {
"end_year":1825,
"name":"james_monroe",
"number":5,
"start_year":1817
},
"john_adams": {
"end_year":1801,
"name":"john_adams",
"number":2,
"start_year":1797
},
"john_quincy_adams": {
"end_year":1829,
"name":"john_quincy_adams",
"number":6,
"start_year":1825
},
"john_tyler": {
"end_year":1845,
"name":"john_tyler",
"number":10,
"start_year":1841
},
"martin_van_buren": {
"end_year":1841,
"name":"martin_van_buren",
"number":8,
"start_year":1837
},
"thomas_jefferson": {
"end_year":1809,
"name":"thomas_jefferson",
"number":3,
"start_year":1801
},
"william_henry_harrison": {
"end_year":1841,
"name":"william_henry_harrison",
"number":9,
"start_year":1841
}
}
true.
This verifies as valid JSON at https://jsonlint.com/
Prompt
For SWI-Prolog create a Prolog predicate to convert president data as JSON to Prolog facts. Use SWI-Prolog libraries as needed.
ChatGPT Completion
Here is a Prolog predicate that converts the JSON data to Prolog facts using the SWI-Prolog libraries:
:- use_module(library(http/json)).
presidents_from_json(Presidents) :-
json_file('presidents.json', JsonData),
dict_pairs(JsonData, presidents, Pairs),
maplist(president_from_json, Pairs, Presidents).
president_from_json(Name-PresDict, president(Number, Name, StartYear, EndYear)) :-
dict_pairs(PresDict, _, [
number-Number,
start_year-StartYear,
end_year-EndYear
]).
The
presidents_from_json/1
predicate reads the JSON data from a file using thejson_file/2
predicate, then converts the dictionary of presidents into a list of key-value pairs using thedict_pairs/3
predicate. It then maps over the pairs using thepresident_from_json/2
predicate to convert each key-value pair into apresident/4
fact.The
president_from_json/2
predicate takes a key-value pair from the JSON data and converts it into apresident/4
fact. It first extracts the name of the president from the key, then extracts the relevant fields from the value dictionary using thedict_pairs/3
predicate. Finally, it unifies the extracted fields with a newpresident/4
fact.
The ChatGPT code has design flaws.
Here is similar working code.
json(Json) :-
Json =
'{
"andrew_jackson": {
"end_year":1837,
"name":"andrew_jackson",
"number":7,
"start_year":1829
},
"george_washington": {
"end_year":1797,
"name":"george_washington",
"number":1,
"start_year":1789
},
"james_madison": {
"end_year":1817,
"name":"james_madison",
"number":4,
"start_year":1809
},
"james_monroe": {
"end_year":1825,
"name":"james_monroe",
"number":5,
"start_year":1817
},
"john_adams": {
"end_year":1801,
"name":"john_adams",
"number":2,
"start_year":1797
},
"john_quincy_adams": {
"end_year":1829,
"name":"john_quincy_adams",
"number":6,
"start_year":1825
},
"john_tyler": {
"end_year":1845,
"name":"john_tyler",
"number":10,
"start_year":1841
},
"martin_van_buren": {
"end_year":1841,
"name":"martin_van_buren",
"number":8,
"start_year":1837
},
"thomas_jefferson": {
"end_year":1809,
"name":"thomas_jefferson",
"number":3,
"start_year":1801
},
"william_henry_harrison": {
"end_year":1841,
"name":"william_henry_harrison",
"number":9,
"start_year":1841
}
}'.
:- dynamic president/4.
presidents_from_json :-
json(Json_string),
open_string(Json_string,Stream),
json_read_dict(Stream, Presidents_dict),
dict_pairs(Presidents_dict,_,Pairs),
pairs_values(Pairs,Values),
dicts_to_compounds(Values, [number,name,start_year,end_year], dict_fill(null), Compounds),
maplist(assert_new_functor(president),Compounds).
assert_new_functor(Functor,Compound0) :-
compound_name_arguments(Compound0,_,Arguments),
compound_name_arguments(Compound,Functor,Arguments),
(
Compound, !
;
assertz(Compound)
).
Example run using SWI-Prolog
?- presidents_from_json.
true.
?- listing(M:president/4).
:- dynamic president/4.
president(7, "andrew_jackson", 1829, 1837).
president(1, "george_washington", 1789, 1797).
president(4, "james_madison", 1809, 1817).
president(5, "james_monroe", 1817, 1825).
president(2, "john_adams", 1797, 1801).
president(6, "john_quincy_adams", 1825, 1829).
president(10, "john_tyler", 1841, 1845).
president(8, "martin_van_buren", 1837, 1841).
president(3, "thomas_jefferson", 1801, 1809).
president(9, "william_henry_harrison", 1841, 1841).
Guess a number
Can ChatGPT generate code that prompts a user for input.
Prompt
In Prolog create a program to allow a user to guess a number by prompting for a number and then replying higher or lower and repeating until the number is found.
ChatGPT Completion
%% Main query to generate guesses
guess(N):-
write('guess a number: '),
read(Guess),
(
Guess == N
-> write('You guessed correctly!');
(
Guess > N
-> write('Lower!'),
nl,
guess(N);
write('Higher!'),
nl,
guess(N)
)
).
Prompt
Demonstrate this code.
ChatGPT Completion
?- guess(7).
guess a number: 5
Higher!
guess a number: 9
Lower!
guess a number: 7
You guessed correctly!
Prompt
Explain the code.
ChatGPT Completion
This code allows a user to guess a number by prompting for a number and then replying higher or lower and repeating until the number is found. The code starts by setting up the main query, guess(N), which prompts the user to guess a number and reads the user’s input. If the user’s input is equal to N (the number to guess), then the user is told that they guessed correctly. If the user’s input is greater than N, then the user is told to guess lower and the query is repeated. If the user’s input is less than N, then the user is told to guess higher and the query is repeated. The query repeats until the user guesses correctly.
Example run using SWI-Prolog
?- guess(23).
guess a number: 10.
Higher!
guess a number: |: 20.
Higher!
guess a number: |: 30.
Lower!
guess a number: |: 24.
Lower!
guess a number: |: 22.
Higher!
guess a number: |: 23.
You guessed correctly!
true.
Notice that each input number ends with a period. This is because the Prolog predicate read/1 expects a Prolog term and all Prolog terms end with a period. A better solution would use read_string/5. See if you can use Prompt Engineering to get ChatGPT to create code for the guessing game using read_string/5.
Prolog modules
Prompt
In Prolog create two files each using use_module. One module is a list of 5 Greek gods and their father. The other module is an ancestor predicate. Demonstrate and explain the code.
ChatGPT Completion
Module 1: gods.pl
% gods.pl
% This module contains a list of five Greek gods and their father
:- module(gods, [god/2]).
god(zeus, kronos).
god(hera, kronos).
god(poseidon, kronos).
god(hades, kronos).
god(ares, zeus).
Module 2: ancestor.pl
% ancestor.pl
% This module contains an ancestor predicate
:- module(ancestor, [ancestor/2]).
:- use_module(gods).
ancestor(X, Y) :-
god(X, Y).
ancestor(X, Y) :-
god(X, Z),
ancestor(Z, Y).
The first module, gods.pl, defines a module gods that contains a predicate god/2 that takes two arguments, X and Y, representing a Greek god and its father. The module contains facts that define the five gods given and their father.
The second module, ancestor.pl, defines a module ancestor that contains a single predicate ancestor
For some reason it did not demonstrate the code so asked separately.
Prompt
Demonstrate the code.
ChatGPT Completion
?- use_module(gods).
true.
?- use_module(ancestor).
true.
?- god(X, kronos).
X = zeus ;
X = hera ;
X = poseidon ;
X = hades ;
false.
?- ancestor(X, kronos).
X = zeus ;
X = hera ;
X = poseidon ;
X = hades ;
X = ares ;
false.
Tabling
Prompt
Create a Prolog predicate to generate Fibonacci numbers using tabling.
ChatGPT Completion
Here’s an implementation of a Prolog predicate to generate the nth Fibonacci number using tabling:
:- table fib/2.
fib(0, 0).
fib(1, 1).
fib(N, F) :-
N > 1,
N1 is N - 1,
N2 is N - 2,
fib(N1, F1),
fib(N2, F2),
F is F1 + F2.
In this implementation, the
:- table fib/2.
directive at the beginning of the code tells Prolog to use tabling for thefib/2
predicate. Tabling is a mechanism for memoization in Prolog that caches the results of predicate calls to avoid redundant computations.The rest of the implementation is similar to the previous implementation, defining two base cases
fib(0, 0)
andfib(1, 1)
, and a recursive casefib(N, F)
to calculate the Nth Fibonacci number. The recursive case uses the Prolog built-inis/2
predicate to evaluate expressions and unify their values with variables. The predicate calculates the (N-1)th and (N-2)th Fibonacci numbers first and then adds them to get the Nth Fibonacci number.With tabling, the results of each calculation are stored in a table, so if the same calculation is performed again in the future, the result can be retrieved from the table instead of re-computing it. This greatly improves the efficiency of the
fib/2
predicate, especially for larger values of N.
Example run using SWI-Prolog
?- maplist(fib,[0,1,2,3,4,5,6,7,8,9,10],F).
F = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].
Collections
Prompt
Create a Prolog facts for eight Greek gods. For each god include three properties.
ChatGPT Completion
god(zeus, king, lightning).
god(hera, queen, marriage).
god(poseidon, sea, earthquakes).
god(demeter, harvest, agriculture).
god(ares, war, courage).
god(aphrodite, love, beauty).
god(athena, wisdom, war).
god(apollo, music, archery).
god(artemis, hunt, wild_animals).
In the above example, each fact is written as “god(Name, Property1, Property2)” where
Name
is the name of the god,Property1
andProperty2
are two of the three properties associated with that god.
findall
Prompt
For the Prolog god facts use the findall predicated to collect the name.
ChatGPT Completion
Here is an example of using the
findall/3
predicate to collect the names of the gods:
all_gods(Gods) :-
findall(Name, god(Name, _, _), Gods).
In the above code, the
findall/3
predicate collects all the names of the gods into a listGods
. The first argument tofindall/3
is the template for the elements to be collected, in this caseName
. The second argument is a goal that defines the elements to be collected, in this casegod(Name, _, _)
. The third argument is the list in which the collected elements are stored, in this caseGods
. The predicateall_gods/1
can be used to obtain the list of all the gods, for example:
?- all_gods(Gods).
Gods = [zeus, hera, poseidon, demeter, ares, aphrodite, athena, apollo, artemis].
setof
Prompt
For the Prolog god facts use the setof predicated to collect the name.
ChatGPT Completion
Here is an example of using the
setof/3
predicate to collect the names of the gods:
all_gods(Gods) :-
setof(Name, god(Name, _, _), Gods).
In the above code, the
setof/3
predicate collects all the names of the gods into a listGods
. The first argument tosetof/3
is the template for the elements to be collected, in this caseName
. The second argument is a goal that defines the elements to be collected, in this casegod(Name, _, _)
. The third argument is the list in which the collected elements are stored, in this caseGods
. The predicateall_gods/1
can be used to obtain the list of all the gods, for example:
?- all_gods(Gods).
Gods = [apollo, ares, artemis, aphrodite, athena, demeter, hera, poseidon, zeus].
Note that
setof/3
returns the collected elements in sorted order, so the list of gods returned by the above code will be sorted alphabetically.
setof/3 is typically used to select all facts sorted. Because setof/3 is used incorrectly the result is different.
Example run using SWI-Prolog
?- all_gods(Gods).
Gods = [demeter] ;
Gods = [artemis] ;
Gods = [zeus] ;
Gods = [aphrodite] ;
Gods = [apollo] ;
Gods = [hera] ;
Gods = [poseidon] ;
Gods = [ares] ;
Gods = [athena]
Here is the corrected code.
all_gods(Gods) :-
setof(Name, [A,B]^god(Name, A, B), Gods).
For details on how to use ^/2 see this reply.
Example run with SWI-Prolog
?- all_gods(Gods).
Gods = [aphrodite, apollo, ares, artemis, athena, demeter, hera, poseidon, zeus].
maplist
Prompt
Create a Prolog maplist predicate that extracts the first two parameters of a functor and returns them as the first two arguments of a functor named edge.
ChatGPT Completion
Here’s a Prolog maplist predicate that extracts the first two parameters of a functor and returns them as the first two arguments of a functor named
edge
:
maplist_edge(List,Result) :-
maplist(extract_edge, List, Result).
extract_edge(Func, edge(First, Second)) :-
Func =.. [_|Args],
[First,Second|_] = Args.
The
maplist_edge/2
predicate uses themaplist/2
predicate to apply theextract_edge/2
predicate to each element of the listList
. Theextract_edge/2
predicate uses=..
(univ operator) to extract the arguments of the input functorFunc
and then uses pattern matching to extract the first two elements of the argument list asFirst
andSecond
.
Predicate signature
Prompt
Show a Prolog predicate with a comment containing the predicate signature.
ChatGPT Completion
Here’s an example Prolog predicate for finding the sum of two numbers:
% sum(+A:integer, +B:integer, -C:integer) is det.
sum(A, B, C) :-
C is A + B.
The predicate signature is as follows:
sum(+A:integer, +B:integer, -C:integer) is det.
This means that
sum/3
is a deterministic predicate that takes two integersA
andB
as input (indicated by the+
sign) and returns the sumC
of the two numbers as output (indicated by the-
sign).
Note: I asked the question the first time and it did not give a correct answer so used thumbs down giving a correct example of a predicate signature. The above is the second time I asked. It also used a different predicate than the first, was really nice to see that it is learning quickly.
Also the SWI-Prolog documentation for sum/3 is
sum(+Vars, +Rel, ?Expr)
notice that the last mode is not -
but ?
.
HTTP server - Hello World
Prompt
Create a SWI-Prolog predicate to serve a Hello World page. Use initialization/1.
ChatGPT Completion
Here is an example of a SWI-Prolog predicate to serve a “Hello World” page using the
http_handler/3
predicate and theinitialization/1
directive:
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- http_handler(root(hello), say_hi, []).
say_hi(Request) :-
format('Content-type: text/plain~n~n'),
format('Hello World!~n').
:- initialization(start_server).
start_server :-
http_server(http_dispatch, [port(8080)]).
The
http_handler/3
predicate sets up a handler for the URL path/hello
, which is handled by thesay_hi/1
predicate. Thesay_hi/1
predicate outputs the text “Hello World!” in plain text format. Theinitialization/1
directive calls thestart_server/0
predicate when the program is loaded, which starts the HTTP server on port 8080 usinghttp_server/2
.
Prompt
How would I start the server and view the page?
ChatGPT Completion
You can start the server by running the following command in the SWI-Prolog console:
?- [file_name].
where
file_name
is the name of the file containing the above code. The server should then start and be ready to receive requests.To view the “Hello World” page, you can open a web browser and go to the following URL:
http://localhost:8080/hello
This will send a request to the server running on
localhost
on port8080
for the/hello
path, which will be handled by thesay_hi/1
predicate and return the “Hello World!” message.
HTTP Server - Web Socket Echo
Prompt
Show code that demonstrates echo using web sockets, do the server using SWI-Prolog in a file named server.pl and the client using HTML in a file named index.html the the JavaScript in a file named echo.js.
ChatGPT Completion
Here is an example code for implementing a simple echo server using web sockets in SWI-Prolog and a client in HTML and JavaScript:
server.pl:
:- use_module(library(http/websocket)).
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- http_handler(root(.), http_upgrade_to_websocket(echo), []).
:- http_handler(root(echo), echo, []).
server(Port) :-
http_server(http_dispatch, [port(Port)]).
echo(WebSocket) :-
ws_receive(WebSocket, Message),
( Message.opcode == close
-> true
; ws_send(WebSocket, Message.data, Message.opcode),
echo(WebSocket)
).
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Echo Client</title>
</head>
<body>
<input type="text" id="input">
<button onclick="send()">Send</button>
<br>
<textarea id="output" cols="50" rows="10"></textarea>
<script src="echo.js"></script>
</body>
</html>
echo.js:
var ws = new WebSocket("ws://localhost:8080/echo");
ws.onopen = function(event) {
console.log("WebSocket connection opened.");
};
ws.onmessage = function(event) {
document.getElementById("output").value += event.data + "\n";
};
ws.onclose = function(event) {
console.log("WebSocket connection closed.");
};
function send() {
var input = document.getElementById("input").value;
ws.send(input);
document.getElementById("input").value = "";
}
This code sets up a simple echo server that listens for WebSocket connections on port 8080. The server simply echoes back any messages it receives from a client. The client is an HTML page that includes a text input and a button to send messages to the server. The JavaScript code creates a WebSocket connection to the server and sends any input from the user to the server. When the client receives a message from the server, it appends the message to a text area on the page.
This is close but needs just a few changes to make it work.
server.pl
:- use_module(library(http/websocket)).
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- initialization
http_server(http_dispatch, [port(8000)]).
:- http_handler(root(.), http_reply_file('index.html', []), []).
:- http_handler(root('echo.js'), http_reply_file('echo.js', []), []).
:- http_handler(
root(echo),
http_upgrade_to_websocket(echo, []),
[spawn([])]
).
echo(WebSocket) :-
ws_receive(WebSocket, Message, [format(json)]),
(
Message.opcode == close
->
true
;
ws_send(WebSocket, Message),
echo(WebSocket)
).
index.html
<!DOCTYPE html>
<html>
<head>
<title>Echo Client</title>
</head>
<body>
<input type="text" id="input">
<button onclick="send()">Send</button>
<br>
<textarea id="output" cols="50" rows="10"></textarea>
<script src="echo.js"></script>
</body>
</html>
echo.js
var ws = new WebSocket("ws://" + window.location.host + "/echo");
ws.onopen = function(event) {
console.log("WebSocket connection opened.");
};
ws.onmessage = function(event) {
const payload = JSON.parse(event.data)
document.getElementById("output").value += payload + "\n";
};
ws.onclose = function(event) {
console.log("WebSocket connection closed.");
};
function send() {
var input = document.getElementById("input").value;
ws.send(JSON.stringify(input))
document.getElementById("input").value = "";
}
Example run
Welcome to SWI-Prolog (threaded, 64 bits, version 9.1.6)
...
?- working_directory(_,'C:/Users/Groot').
true.
?- [server].
% Started server at http://localhost:8000/
true.
?-
Using Internet browser
URL: http://localhost:8000/
Enter text then press Send
Meta predicates
Getting ChatGPT to create this took more than 10 attempts at the prompt. Even gave up on giving ChatGPT the working code first and asking it to create a prompt. It just never seemed to know how to use meta_predicate as a directive which is why the prompt is so specific about that.
Prompt
Create two modules, the first module ‘indirection’ contains the predicate display_list/1 with a goal argument. display_list/1 is a meta_predicate so a meta_predicate directive needs to be used. The second module
examples
uses use_module for the module ‘indirection’ and contains two predicates, nodes/1 that returns a list, check/0 that calls display_list and passes the goal ‘nodes’. Put the code in a code block for readability.
ChatGPT Completion
%Module 1 - indirection.pl
:- module(indirection, [display_list/1]).
:- meta_predicate display_list(0).
display_list(Goal) :-
call(Goal, List),
write(List).
%Module 2 - examples.pl
:- module(examples, [check/0]).
:- use_module(indirection).
nodes(Nodes) :- Nodes = [1, 2, 3, 4, 5].
check :- display_list(nodes).
The first time a reply with working code the meta_predicate was
:- meta_predicate display_list(:).
and this time it is
:- meta_predicate display_list(0).
both ways work.