Daniel Porteous
Daniel Porteous

Reputation: 6353

How to get the next ascii char in Prolog?

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

Answers (1)

user1812457
user1812457

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

Related Questions