SWI-Prolog 中的可逆谓词和字符串

2024-03-04

append/3是一个非常强大的谓词。假设我想要一个以相同方式工作但针对 SWI-Prolog 字符串的谓词。

我看到的最简单的方法是将这些字符串转换为列表string_codes/2,然后应用append/3,然后使用string_codes/2后退。这种方法的一个大问题是string_codes/2如果两个变量不统一,则不起作用。

这是我想出的一个极其丑陋的解决方案,它检查哪些字符串是统一应用的string_codes/2需要的时候:

append_strings(S1, S2, S3) :-
    nonvar(S1),
    nonvar(S2),!,
    string_codes(S1, A),
    string_codes(S2, B),
    append(A,B,C),
    string_codes(S3, C).

append_strings(S1, S2, S3) :-
    nonvar(S1),
    nonvar(S3),!,
    string_codes(S1, A),
    string_codes(S3, C),
    append(A,B,C),
    string_codes(S2, B).

append_strings(S1, S2, S3) :-
    nonvar(S2),
    nonvar(S3),!,
    string_codes(S2, B),
    string_codes(S3, C),
    append(A,B,C),
    string_codes(S1, A).

append_strings(S1, S2, S3) :-
    nonvar(S3),
    string_codes(S3, C),
    append(A,B,C),
    string_codes(S1, A),
    string_codes(S2, B).

对于以下情况,这会产生正确的结果:

?- append_strings("test","auie","testauie").
true.

?- append_strings("test",A,"testauie").
A = "auie".

?- append_strings(A,"auie","testauie").
A = "test" ;
false.

?- append_strings(A,B,"testauie").
A = "",
B = "testauie" ;
A = "t",
B = "estauie" ;
A = "te",
B = "stauie" ;
A = "tes",
B = "tauie" ;
A = "test",
B = "auie" ;
A = "testa",
B = "uie" ;
A = "testau",
B = "ie" ;
A = "testaui",
B = "e" ;
A = "testauie",
B = "" ;
false.

难道真的没有比这更简单的方法了吗?假设我想创建一大堆谓词来处理字符串,就像处理列表一样:我显然不想写我所做的事情append/3对于他们所有人。但我也不想使用代码字符串,因为这样我就无法知道我是在操作普通列表还是真正的字符串。


由于谓词适用于列表,因此我似乎很想使用 DCG。首先让我们观察一下 Prolog 中的字符串实际上是字符代码的列表:

   ?- X="test".
X = [116,101,115,116]

当然,这不太可读,所以让我们看看字符本身而不是它们的代码:

   ?- set_prolog_flag(double_quotes,chars).
yes
   ?- X="test".
X = [t,e,s,t]

这样更好。考虑到谓词应该描述的关系,我选择了一个描述性名称,例如 list_list_append/3。这个谓词有一个目标:一个 dcg 规则,我们称之为 list_list//2,它使用另一个 dcg,我们称之为 list//2,来实际编写列表:

list_list_appended(L1,L2,L3) :-
    phrase(list_list(L1,L2),L3).   % L3 is L1+L2

list([]) -->                       % if the list is empty ...
    [].                            % ... there's nothing in the list
list([X|Xs]) -->                   % if there's a head element ...
    [X],                           % ... it's in the list
    list(Xs).                      % the tail is also a list

list_list(L1,L2) -->               % the list consists of ...
    list(L1),                      % ... L1 followed by ...
    list(L2).                      % L2

您的示例查询:

   ?- list_list_appended("test","auie","testauie").
yes
   ?- list_list_appended(L1,"auie","testauie").
L1 = [t,e,s,t] ? ;
no
   ?- list_list_appended("test",L2,"testauie").
L2 = [a,u,i,e] ? ;
no
   ?- list_list_appended("test","auie",L3).
L3 = [t,e,s,t,a,u,i,e]
   ?- list_list_appended(L1,L2,"testauie").
L1 = [],
L2 = [t,e,s,t,a,u,i,e] ? ;
L1 = [t],
L2 = [e,s,t,a,u,i,e] ? ;
L1 = [t,e],
L2 = [s,t,a,u,i,e] ? ;
L1 = [t,e,s],
L2 = [t,a,u,i,e] ? ;
L1 = [t,e,s,t],
L2 = [a,u,i,e] ? ;
L1 = [t,e,s,t,a],
L2 = [u,i,e] ? ;
L1 = [t,e,s,t,a,u],
L2 = [i,e] ? ;
L1 = [t,e,s,t,a,u,i],
L2 = [e] ? ;
L1 = [t,e,s,t,a,u,i,e],
L2 = [] ? ;
no

作为 SWI 用户,您还可以使用这个图书馆 http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/double_quotes.pl结合set_prolog_flag(double_quotes,chars).以获得所需形式的输出。参考这个答案 https://stackoverflow.com/a/8269897/6101159了解详情。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SWI-Prolog 中的可逆谓词和字符串 的相关文章

随机推荐