将输入流转换为 ASCII:Prolog 代码的解释

Converting input stream to ASCII: explanation of Prolog code

我正在尝试使用 Prolog 谓词读取字符串并将其转换为 ASCII 值 read_command/1

以下代码有效。有人可以解释一下如何理解下面这段代码吗?

read_command(L) :-             % read_command/1
    get0(C),
    read_command(_, L, C).

read_command(_, [], X) :-      % auxiliary predicate read_command/3
    member(X, `.\n\t`),
    !.
read_command(X, [C|L], C) :-
    get0(C1),
    read_command(X, L, C1).

read_command/1 从当前输入流中读取第一个可用字符,并将其用作 lookahead.

read_command/3 当前瞻是空格或点时停止。 否则,将前瞻放入列表,从流中获取新的前瞻,然后递归。

我认为 read_command/3 的第一个子句也应该处理 X 为 -1 的情况,表示文件结束(例如,在按下 Ctrl+D 之后)

TL;DR: 不要使用 get0/1!

get0/1 被认为 已弃用 — 即使是实现它的 Prolog 处理器(如 SWI)也是如此。

相反,使用 get_char/1 并将字符串表示为字符列表——而不是 作为代码列表!

read_command(Chars) :-
   get_char(Next),
   read_command_aux(Chars, Next).

read_command_aux(Chars, Char) :-
   member(Char, ['.', '\t', '\n', end_of_file]),
   !,
   Chars = [].
read_command_aux([Char|Chars], Char) :-
   get_char(Next),
   read_command_aux(Chars, Next).

以下是一些使用 SWI-Prolog 7.3.15 的示例查询:

?- read_command(Chars).
|: abc
Chars = [a, b, c].

?- read_command(Chars).
|: abc.

Chars = [a, b, c].

?- read_command(Chars).
|: 123abc
Chars = ['1', '2', '3', a, b, c].

要进一步使用命令,您可能需要使用 atom,如下所示:

?- read_command(Chars), atom_chars(Command, Chars).
|: abcd.

Chars = [a, b, c, d],
Command = abcd.

请注意,这 不仅适用于 SWI,而且适用于 SICStus Prolog 4.3.2(及其他)。