Reputation: 6353
I want a predicate that works like this:
next_char(Curr, Next) :-
Next is Curr + 1.
Which I could call like this:
next_char('D', X).
In which it would give me X='E'
.
Unfortunately it doesn't seem like you can do this arithmetic on chars in Prolog. Cheers.
Upvotes: 0
Views: 627
Reputation:
If you only want to cover the printable ASCII characters (32-127), you could simply make a "table" with all the characters and put it in the database. This is just a small example what it would look like:
% space is the first printable ASCII character
asciichar_succ(' ', '!').
asciichar_succ('!', '"').
% ...
asciichar_succ(a, b).
asciichar_succ(b, c).
% ...
asciichar_succ('}', '~').
One way to add this to the database would be to use compile-time term expansion, for example like this:
term_expansion(asciichar_succ(_, _), Chars) :-
findall(asciichar_succ(C0, C1), asciichar_next(C0, C1), Chars).
asciichar_next(C0, C1) :-
between(32, 125, Code0),
succ(Code0, Code1),
char_code(C0, Code0),
char_code(C1, Code1).
asciichar_succ(_, _).
When I put this in a file char_succ.pl
, and load this file from the SWI-Prolog top level, I get:
?- [char_succ].
true.
?- asciichar_succ(a, X).
X = b.
?- asciichar_succ(X, '"').
X = !.
?- listing(asciichar_succ/2).
asciichar_succ(' ', !).
asciichar_succ(!, '"').
asciichar_succ('"', #).
asciichar_succ(#, $).
asciichar_succ($, '%').
asciichar_succ('%', &).
% ...
asciichar_succ(?, @).
asciichar_succ(@, 'A').
asciichar_succ('A', 'B').
asciichar_succ('B', 'C').
% ...
asciichar_succ(y, z).
asciichar_succ(z, '{').
asciichar_succ('{', '|').
asciichar_succ('|', '}').
asciichar_succ('}', ~).
true.
Doing it like this has one very nice property: as long as at least one of the two arguments is ground, the predicate is deterministic and doesn't leave behind any choice points. In other words, asciichar_succ/2
is a "true relation". You can definitely achieve the same end result with arithmetic at run time, but it will be a bit hairier to get right.
Upvotes: 1