Convert a char list to a string in Prolog - prolog

I'm trying to convert a char array to a string, and then convert this string a list. This is what I want:
code_list=[97 97]
string_s="aa"
string_list=[aa]
I'm not sure about notation, whether I used them correctly or not.

A few examples that may help you understand the different ways to represent "strings" in SWI-Prolog, and convert from one representation to another (note that Prolog doesn't really have types, so this is not a type converstion).
This is all for SWI-7 and later:
$ swipl --version
SWI-Prolog version 7.1.27 for x86_64-linux
Now, from the top level:
?- atom(foo).
true.
?- string("foo").
true.
?- is_list(`foo`).
true.
?- is_list([f,o,o]).
true.
?- atom_chars(A, [f,o,o]).
A = foo.
?- atom_codes(foo, Codes).
Codes = [102, 111, 111].
?- string_codes(Str, `foo`).
Str = "foo".
?- write(`foo`).
[102,111,111]
true.
?- string_chars(Str, [f,o,o]).
Str = "foo".
You should read the documentation on the used predicates if you want to learn a bit more.

Commonly, Prolog systems do not support a separate string data type. Instead, there are atoms, lists of codes, and lists of characters which serve the very purpose of strings. So if you are learning Prolog, stick to those types. The following query works in any Prolog system:
?- Code_list = [97, 97], atom_codes(Atom, Code_list), atom_chars(Atom, Chars).
Code_list = [97,97], Atom = aa, Chars = [a,a].
This should answer your question.
For completeness, remark that strings as a separate data type are very rare. And most often they are not a valid extension to the ISO Prolog standard.
SWI7 has particularly odd behavior with respect to strings. The first thing to try is the following query:
?- phrase("abc","abc").
This query should succeed, otherwise learning DCGs (one of Prolog's main features) will be very cumbersome to you. In SWI7 the default is:
?- phrase("abc","abc").
ERROR: Type error: `list' expected, found `"abc"' (a string)
So the double quote notation means two different things. To get consistent behavior, you have several options.
Install SWI Prolog 6, or another system like GNU or SICStus Prolog.
Call SWI with swipl --traditional which fixes many of the incompatibilities.
Change the Prolog flag double_quotes to codes or chars. See this answer how this is done.

The proper way to express your example would be:
Code_list = [97, 97]
String_s = "aa"
(I'm not quite sure what you mean by the last line.)

Related

Listing/1 with char codes displayed as characters and not codes?

Using SWI-Prolog
Version:
?- current_prolog_flag(windows,Value).
Value = true.
?- current_prolog_flag(version,Value).
Value = 80000.
For a simple DCG
constant_value --> "ID".
listing/1 outputs
?- listing(constant_value).
constant_value([73, 68|A], A).
However in my notes I have it as
?- listing(constant_value).
constant_value(['I', 'D'|A], A).
but I don't know what I did to have the character codes appear as characters.
I tried the SWI-Prolog flag double_quotes with various values (chars, codes, string) but can't reproduce the desired output.
How are listing/1 of a DCG created where the character codes are displayed as characters?
I think that you probably had double_quotes flag in codes when constant_value was compiled. The value of this flag won't affect clauses already stored in the database.
constant_value1 --> "ID".
:-set_prolog_flag(double_quotes, chars).
constant_value2 --> "ID".
?- listing(constant_value1).
constant_value1([73, 68|A], A).
?- listing(constant_value2).
constant_value2(['I', 'D'|A], A).
Edit by Guy Coder
Since I use the Q&A at SO as a personal notebook with my own Q&A, I tend to look at the accepted answer for the details; I am adding them here for everyone's benefit.
As this answer correctly states, the problem was caused by the fact that originally in the source code, which was a module stored as a file, I had the statement
:- set_prolog_flag(double_quotes,chars).
before the code
constant_value --> "ID".
then in the REPL
?- consult('C:/dcg_examples.pl').
?- listing(constant_value).
constant_value(['I', 'D'|A], A).
true.
and to use this
?- phrase(constant_value,"ID").
true.
Latter in the source code I changed the value for double_quotes
:- set_prolog_flag(double_quotes,codes).
notice the change from chars to codes
Restarting the REPL and doing the same
?- consult('C:/dcg_examples.pl').
?- listing(constant_value).
constant_value([73, 68|A], A).
true.
?- phrase(constant_value,"ID").
true.
gave the different result for listing/1.
However in the REPL using
set_prolog_flag(double_quotes,<VALUE>).
had no effect on the result of listing/1.
<VALUE> can be one of string, chars, codes, traditional, or atom.
The key point to note here is that listing/1 uses consulted/compiled/stored code. So the value of double_quotes at the time of consulting/compiling/storing is what listing/1 uses. Any changes to double_quotes after that in the REPL will not change the consulted/compiled/stored code and thus the result of listing/1.
To effect a change you have to add
:- set_prolog_flag(double_quotes,<VALUE>).
in your source code before the predicate then consult/1 to load it and then listing/1.
The meaning of consulted/compiled/stored does not imply that these are three separate actions performed in a sequence, here they define when the source code is put into the database for use by listing/1.

Alternative to string_upper/2

Machine, which my code is supposed to work on, for some reason doesn't know predicate string_upper/2. Are there any alternatives? Eventually, what would code for this predicate look like?
The example you gave in the comments is actually not a string but a pair of atoms. Since you already opted to use upcase_atom/2, in the code you deleted from your post, I'd point out that this built-in is only working in one direction, that is if the the first argument is atomic. Consider the following queries:
?- upcase_atom(bo,'BO'). % Is 'BO' the uppercase version of bo?
true. % Yes, it is.
?- upcase_atom(bo,B). % What's the uppercase version of bo?
B = 'BO'. % It's 'BO'
?- upcase_atom(B,'BO'). % What atom has 'BO' as uppercase version?
ERROR: upcase_atom/2: Arguments are not sufficiently instantiated
?- upcase_atom(B,1). % What atom has 1 as uppercase version?
ERROR: upcase_atom/2: Arguments are not sufficiently instantiated
Your example query, from your deleted code, is ?- divideIt(a-b).. The atom a is unified with the variable V in the head of the rule divideIt/1. Then Prolog calls the first goal upcase_atom(V,ve) that has to fail because the atom ve is not the uppercase version of the atom a. Consequently your example query fails as well. If you apply the following minor changes to your predicate, it yields the desired result:
divideIt(V-W) :-
upcase_atom(V,Ve), % <- Ve (=variable) instead of ve (=atom)
write(Ve),
write('-'), % <- '-' instead of "-"
upcase_atom(W,We), % <- We (=variable) instead of we (=atom)
write(We).
?- divideIt(a-b).
A-B
true.
Break the string into a list of character codes. Then convert those codes into the appropriate upper case code if necessary before reconstructing the string. A more complete answer would require knowing which prolog you're using, its available predicates & how it represents strings.
You might want to read up on different Prolog's handling of characters, Unicode and strings. For this, the SWI-Prolog implementation has some good documentation:
How traditional(Edinburgh), ISO & SWI prolog handles characters: 4.2 Character Representation
How ISO & SWI prologs support Unicode 2.16.1.8 Unicode Prolog source
How SWI has a specific string-type object which uses quotes to denote them: 5.2 The string type and its double quoted syntax

Prolog type errors with DCG library functions

I'm trying to write a DCG for a command interface. The idea is to read a string of input, split it on spaces, and hand the resulting list of tokens to a DCG to parse it into a command and arguments. The result of parsing should be a list of terms which I can use with =.. to construct a goal to call. However, I've become really confused by the string type situation in SWI-Prolog (ver. 7.2.3). SWI-Prolog includes a library of basic DCG functionality, including a goal integer//1 which is supposed to parse an integer. It fails due to a type error, but the bigger problem is that I can't figure out how to make a DCG work nicely in SWI-Prolog with "lists of tokens".
Here's what I'm trying to do:
:- use_module(library(dcg/basics)).
% integer//1 is from the dcg/basics lib
amount(X) --> integer(X), { X > 0 }.
cmd([show,all]) --> ["show"],["all"].
cmd([show,false]) --> ["show"].
cmd([skip,X]) --> ["skip"], amount(X).
% now in the interpreter:
?- phrase(cmd(L), ["show","all"]).
L = [show, all].
% what is the problem with this next query?
?- phrase(cmd(L), ["skip", "50"]).
ERROR: code_type/2: Type error: `character' expected, found `"50"' (a string)
I have read Section 5.2 of the SWI manual, but it didn't quite answer my questions:
What type is expected by integer//1 in the dcg/basics library? The error message says "character", but I can't find any useful reference as to what exactly this means and how to provide it with "proper" input.
How do I pass a list of strings (tokens) to phrase/2 such that I can use integer//1 to parse a token as an integer?
If there's no way to use the integer//1 primitive to parse a string of digits into an integer, how should I accomplish this?
I did quite a bit of expermenting with using different values for the double_quote flag in SWI-Prolog, plus different input formats, such as using a list of atoms, using a single string as the input, i.e. "skip 50" rather than ["skip", "50"], and so on, but I feel like there are assumptions about how DCGs work that I don't understand.
I have studied these three pages as well, which have lots of examples but none quite address my issues (some links omitted since I don't have enough reputation to post all of them):
The tutorial "Using Definite Clause Grammars in SWI-Prolog" by Anne Ogborn
A tutorial from Amzi! Prolog about writing command interfaces as DCGs.
Section 7.3 of J. R. Fisher's Prolog tutorial
A third, more broad question is how to generate an error message if an integer is expected but cannot be parsed as one, something like this:
% the user types:
> skip 50x
I didn't understand that number.
One approach is to set the variable X in the DCG above to some kind of error value and then check for that later (like in the hypothetical skip/1 goal that is supposed to get called by the command), but perhaps there's a better/more idiomatic way? Most of my experience in writing parsers comes from using Haskell's Parsec and Attoparsec libraries, which are fairly declarative but work somewhat differently, especially as regards error handling.
Prolog doesn't have strings. The traditional representation of a double quoted character sequence is a list of codes (integers). For efficiency reasons, SWI-Prolog ver. >= 7 introduced strings as new atomic data type:
?- atomic("a string").
true.
and backquoted literals have now the role previously held by strings:
?- X=`123`.
X = [49, 50, 51].
Needless to say, this caused some confusion, also given the weakly typed nature of Prolog...
Anyway, a DCG still works on (difference) lists of character codes, just the translator has been extended to accept strings as terminals. Your code could be
cmd([show,all]) --> whites,"show",whites,"all",blanks_to_nl.
cmd([show,false]) --> whites,"show",blanks_to_nl.
cmd([skip,X]) --> whites,"skip",whites,amount(X),blanks_to_nl.
and can be called like
?- phrase(cmd(C), ` skip 2300 `).
C = [skip, 2300].
edit
how to generate an error message if an integer is expected
I would try:
...
cmd([skip,X]) --> whites,"skip",whites,amount(X).
% integer//1 is from the dcg/basics lib
amount(X) --> integer(X), { X > 0 }, blanks_to_nl, !.
amount(unknown) --> string(S), eos, {print_message(error, invalid_int_arg(S))}.
prolog:message(invalid_int_arg(_)) --> ['I didn\'t understand that number.'].
test:
?- phrase(cmd(C), ` skip 2300x `).
ERROR: I didn't understand that number.
C = [skip, unknown] ;
false.

Using the prolog format predicate to print to file

Is it possible to use the prolog format predicate to print to file?
I have a table of data that I print to stdout using the format predicate, i.e.
print_table :-
print_table_header,
forall(range(1.0,10.0,0.1,N), print_row(N,L)).
%% print_row(L) :- take a list of the form, [a,b,c,d,e] and
%% print it to screen as a single row of tab separated float values (1DP)
print_row(N,L) :-
build_row(N,L),
format('~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~n', L).
print_table_header :-
format('~t~w~10+ ~t~w~10+ ~t~w~10+ ~t~w~10+ ~t~w~10+ ~n', ['N','N2','N3','N4','N5']).
would be nice to somehow reuse the code to print the same thing to file.
In addition to the other good answer (+1!), I would like to present a purer solution to such tasks.
The key idea is to make format/2 accessible within DCGs, and then to use a DCG to describe the output.
This is very easy, using the codes argument of format/3, provided by several Prolog implementations. All you need are the following short auxiliary definitions:
format_(Data, Args) --> call(format_dlist(Data, Args)).
format_dlist(Data, Args, Cs0, Cs) :- format(codes(Cs0,Cs), Data, Args).
The nonterminal call//1 calls its argument with two additional arguments that let you access the implicit DCG arguments, and this is used to describe additional codes via format/3.
Now, we can simply use the nonterminal format_//2 within DCGs.
For example, to describe a simple table:
table -->
row([a,b,c]),
row([d,e,f]).
row(Ls) --> format_("~t~w~10+~t~w~10+~t~w~10+~n", Ls).
Usage example and result:
?- phrase(table, Cs), format("~s", [Cs]).
a b c
d e f
Cs = [32, 32, 32, 32, 32, 32, 32, 32, 32|...].
Note that one last remaining format/2 is used to actually write the output to the screen.
However, everything else is free of side-effects and declaratively describes a table.
An important advantage of this method is that you can easily write test cases to see whether your tables are (still) correctly formatted. It is easy to reason about Prolog lists of codes (described with a DCG), but quite hard to reason about things that only appear on the terminal.
You can!
Consider the following extract of the SICStus Prolog documentation for format/[2,3]:
11.3.85 format/[2,3]
Synopsis
format(+Control, +Arguments)
format(+Stream, +Control, +Arguments)
Interprets the Arguments according to the Control string and prints the result on Stream.
The predicates format/[2,3] are widely supported across Prolog implementations.
However, as of right now, these predicates are not part of ISO Prolog.
I would write the output 'routines' with an additional parameter, a Stream, and then I would pass user while testing or printing to screen. See ISO predicates open/3, close/1 etc for stream handling...
Note that IO it's among the least 'declarative' areas of the language, because, for efficiency, an approach based on side effects is required...
SWI-Prolog has a builtin with_output_to, that would allows to reuse your existing code without adding a parameter. But since you tagged iso-prolog your question, you should really add the Stream parameter...

What is the meaning of predicate "simple/1" in Prolog (SWI-Prolog)

I run into problem while reading a book.
I see a program use predicate "simple" ( I guess simple/1 ). I don't know what is the meaning of this predicate, I can't find it with ?-help(simple) in the console.
But when I tried with some queries in console, it worked something like:
5 ?- simple(p(x)).
false.
6 ?- simple(mia).
true.
7 ?- simple(Mia).
true.
8 ?- simple(f(Mia)).
false.
I guess it is some sort of predicate to determine if the argument was Terms(or Variables) or Complex Terms.
The swi-prolog manual has the following definition:
simple(#Term) is semidet
Term is atomic or a variable.
the definition is in the quintus prolog compatibility library; in the quintus prolog documentation the definition is:
simple(+Term)
Term is currently instantiated to either an atom, a number, a database
or a variable.
in any case, simple/1 is true if the argument is a simple term (not sure what the quintus manuals means by database; possibly a handler for an ODBC connection i guess)
translated to ISO predicates:
simple(T) :- var(T) ; atomic(T).
var/1 it's the most basic metaprogramming device, because it's impossible to predicate (i.e. execute code, binding variables) about any clause without instancing the variables, that are many times the essential part we are interested to.

Resources