String Formatting in Prolog
Our example demonstrates various string formatting techniques in Prolog. While Prolog doesn’t have a built-in printf-style formatting system like some other languages, we can achieve similar results using Prolog’s powerful string manipulation predicates.
:- use_module(library(format)).
% Define a point structure
point(X, Y) :- number(X), number(Y).
main :-
% Create a point
P = point(1, 2),
% Basic structure printing
format('struct1: ~w~n', [P]),
% Printing with more detail
format('struct2: point(x:~w, y:~w)~n', [1, 2]),
% Printing the type
format('type: ~w~n', [point]),
% Formatting booleans
format('bool: ~w~n', [true]),
% Formatting integers
format('int: ~d~n', [123]),
% Binary representation
format('bin: ~2r~n', [14]),
% Character representation
format('char: ~c~n', [33]),
% Hexadecimal representation
format('hex: ~16r~n', [456]),
% Formatting floats
format('float1: ~f~n', [78.9]),
format('float2: ~e~n', [123400000.0]),
format('float3: ~E~n', [123400000.0]),
% String formatting
format('str1: ~w~n', ["string"]),
format('str2: ~q~n', ["string"]),
% Hexadecimal representation of a string
string_codes("hex this", Codes),
format('str3: ~16r~n', [Codes]),
% Pointer representation (not applicable in Prolog, using object identity instead)
format('identity: ~w~n', [P]),
% Width formatting for integers
format('width1: |~`_t~6d|~`_t~6d|~n', [12, 345]),
% Width formatting for floats
format('width2: |~`_t~6.2f|~`_t~6.2f|~n', [1.2, 3.45]),
% Left-justified width formatting for floats
format('width3: |~`_t~6.2f|~`_t~6.2f|~n', [1.2, 3.45]),
% Width formatting for strings
format('width4: |~`_t~6s|~`_t~6s|~n', ["foo", "b"]),
% Left-justified width formatting for strings
format('width5: |~6s|~6s|~n', ["foo", "b"]),
% Equivalent to Sprintf
format(string(S), 'sprintf: a ~w', ["string"]),
format('~w~n', [S]),
% Writing to a different stream (stderr in this case)
format(user_error, 'io: an ~w~n', ["error"]).
To run this program, save it as string_formatting.pl
and use your Prolog interpreter. For example, with SWI-Prolog:
$ swipl -s string_formatting.pl -g main -t halt
struct1: point(1,2)
struct2: point(x:1, y:2)
type: point
bool: true
int: 123
bin: 1110
char: !
hex: 1C8
float1: 78.900000
float2: 1.234000e+08
float3: 1.234000E+08
str1: string
str2: "string"
str3: 6865782074686973
identity: point(1,2)
width1: |____12|___345|
width2: |__1.20|__3.45|
width3: |__1.20|__3.45|
width4: |___foo|_____b|
width5: |foo |b |
sprintf: a string
io: an error
Note that Prolog’s formatting capabilities differ from those in some other languages. We’ve used the format/2
and format/3
predicates from the format
library to achieve similar results. Some concepts, like pointers, don’t directly apply to Prolog, so we’ve adapted them as best as possible.
The width formatting in Prolog works differently. We’ve used the ~
_tformat specifier for right-justified padding with underscores. For left-justified formatting of strings, we simply use the
~Ns` format specifier where N is the width.
Prolog doesn’t have a direct equivalent to Printf
or Sprintf
, but we can use format/3
with a string as the first argument to capture the formatted output in a variable.
Lastly, to write to a different stream (like stderr), we can specify the stream as the first argument to format/3
. In this case, we’ve used user_error
which is typically linked to stderr.