fal*_*lse 11 prolog iso-prolog
当使用字符(字符列表,因此长度为一的原子)来表示文本时,我们可以使用以下选项将它们写入术语中:
"First,"双引号列表表示法 (6.3.7) 是最有效的一种,至少需要n+2 个字符。double_quotes但只有当 Prolog 标志设置为chars时才能读回。
['N',e,x,t,',']出现至少2n+1 个字符的列表符号。虽然它很好并且相对紧凑,但它意味着在写入其他数据时也会使用运算符,因为它是通过 启用的ignore_ops(false),并且这需要在读取时出现相同的运算符,这使得它非常脆弱。
'.'('L','.'(a,'.'(s,'.'(t,'.'(',',[])))))使用函数形式的规范表示法也适用于需要至少7n+2 个字符的列表。这是很多,但对于互操作性(包括与同一系统的互操作性)来说这是最好的,因为它既不依赖于标志double_quotes也不依赖于各种运算符声明。
以规范表示法写入字符可以在常量空间中完成。但对于阅读来说,情况就有点棘手了。毕竟,以 开头的序列'.'(a,也可以指代术语'.'(a,Further,b)。因此,天真的阅读必须等待(并使用空间),直到读入整个字符列表。另一方面,这似乎是一个安全的赌注,'.'(a,将是一个列表构造函数'.'(a,Further)。换句话说,
如何使用规范符号来读取术语,并使用恒定的辅助空间来读取其中的字符?
如果有帮助,请考虑条款sampleterm/1。因此,请考虑阅读以规范形式编写的所有此类术语。并且,如果您愿意,可以将其表述为 DCG。
sampleterm([]).
sampleterm(a).
sampleterm(b).
sampleterm('.'(E,Es)) :- % the real list constructor
sampleterm(E),
sampleterm(Es).
sampleterm('.'(E,F,G)) :- % no list constructor
sampleterm(E),
sampleterm(F),
sampleterm(G).
Run Code Online (Sandbox Code Playgroud)
如果这种节省空间的读取是可能的,那么支持诸如 Scryer 和 Trealla 之类的紧凑内部字符表示的系统甚至可以更进一步。
啊,以免我忘记我尝试过的:read/1确实如此,但目前并不理想。
以下简单的代码基于 Prolog 流。
它专注于从可重新定位流中读取“真实列表样本树”。
对于 (1) 不可重新定位的流和 (2) 处理,'.'/3我们回退到read/1.
主要谓词是read_sampleterm/1:
read_sampleterm(术语) :-
当前输入(S),
(stream_property(S,重新定位(true)),
流属性(S,位置(P)),
( aux_read_sampleterm_1(Term0),
get_char('.') % 这太草率了!
-> 正确
; 设置流位置(S,P),
失败
)
-> 术语=术语0
; 读取(术语)% 回退
)。
请注意,上面的代码很草率:在读取结束时,我们需要确保后面有 EOF 或不与 结合的字符'.'。
实际的读取是通过以下辅助谓词完成的:
aux_read_sampleterm_1(术语):-
get_char(Ch),
aux_read_sampleterm_2(通道,术语,0)。% 使用索引
aux_read_sampleterm_2('\'',[X|Xs],N0) :-
get_char('.'),
get_char('\''),
get_char('('),
aux_read_sampleterm_1(X),
get_char(','),
N1 是 N0 + 1,
get_char(Ch),
aux_read_sampleterm_2(Ch,Xs,N1)。
aux_read_sampleterm_2('[',[],N) :-
get_char(']'),
eat_rparens(N)。
aux_read_sampleterm_2(a,a,N) :-
eat_rparens(N)。
aux_read_sampleterm_2(b,b,N) :-
eat_rparens(N)。
eat_rparens(N) :-
(N > 0
-> get_char(')'),
N0 为 N-1,
eat_rparens(N0)
; 真的
)。
为了展示一些简单的用例,我们从文件中读取:
read_sampleterm_from_file(文件,术语) :-
打开(文件,读取,S,[类型(文本)]),
当前输入(S0),
设置输入(S),
read_sampleterm(Term0),
设置输入(S0),
关闭(S),
期限 = 期限 0。
使用 GNU Prolog 1.5.0 的示例查询:
第一的,sample1.txt:
'.'(a,'.'(b,[]))。
我们得到:
| ?- read_sampleterm_from_file('sample1.txt',T)。
T = [a,b]
是的
下一个,sample2.txt:
'.'(a,'.'(b,a))。
我们得到:
| ?- read_sampleterm_from_file('sample2.txt',T)。
T = [a,b|a]
是的
sample3.txt接下来是:
'.'('.'(a,'.'(b,'.'(a,[]))),[])。
我们得到:
| ?- read_sampleterm_from_file('sample3.txt',T)。
T = [[a,b,a]]
(1 毫秒)是
请注意,运行上述测试是在没有“后备选项”的情况下运行的。