Prolog中的简单附加问题
几周前,我一直在学习Prolog,而我一直坚持的一件小事就是使用append提出解决方案 例如,如果我有一个模式匹配规则Prolog中的简单附加问题,prolog,Prolog,几周前,我一直在学习Prolog,而我一直坚持的一件小事就是使用append提出解决方案 例如,如果我有一个模式匹配规则 pattern( foo(X,Y), L1, L ) :- % some code to go through a list (where the foo-pattern is) % and add the pattern to the list L if it matches` 我知道append/3是这里的方式,但是。。L开始未知,即不接地,当我们开始递
pattern( foo(X,Y), L1, L ) :-
% some code to go through a list (where the foo-pattern is)
% and add the pattern to the list L if it matches`
我知道append/3是这里的方式,但是。。L开始未知,即不接地,当我们开始递归列表时,它开始填充匹配的模式。然而,我总是对最初发生的事情感到困惑,即当L不接地时
例如,这里有一段断断续续的代码,当第一个参数是可能模式的列表时,我们希望获得所有匹配模式的列表:
pat([foo(X,Y)|L1], R, L) :-
append(foo(X,Y),R,L),
pat(L1, R, [D|L]).
pat([_|L1], R, L2) :-
pat(L1, R, L2).
非常感谢。您可能会得到一个不使用
append/3
的解决方案。例如,考虑下面的谓词,<代码>过滤器/ 3 < /代码>:
filter(_Pattern, [], []).
filter(Pattern, [E|Es], Matches) :-
Pattern \= E, !,
filter(Pattern, Es, Matches).
filter(Pattern, [E|Es], [E|Matches]) :-
filter(Pattern, Es, Matches).
filter_list(_Patterns, [], []).
filter_list(Patterns, [E|Es], Matches) :-
filter(E, Patterns, []), !,
filter_list(Patterns, Es, Matches).
filter_list(Patterns, [E|Es], [E|Matches]) :-
filter_list(Patterns, Es, Matches).
filter/3
的第一个子句是基本情况,如果第二个参数列表中没有(左)匹配项,那么我们将得到一个空列表。因为我们没有考虑<代码>模式< /代码>,所以忽略了它(因此前面的<代码> < /代码>对变量)。
filter/3
的第二个子句测试Pattern
,它可以绑定到一个术语(例如foo(X,Y)
),是否可以与列表中要匹配的第一个元素e
相统一。\=
运算符将在其参数无法统一时成功,因此如果成功,当我们没有将E
与模式匹配时,可以将其丢弃并继续(请注意,在测试后剪切!
以提交到此分支)
filter/3
的最后一个(第三个)子句依赖于第二个子句,因为它只是将E
传递到最后一个参数列表Matches
,假设它与模式
匹配,因为前面的子句无法确定它不匹配。请注意,我们通过将列表结构绑定到输出,将匹配项保持为未绑定状态,从而将E
附加到列表中;完整的匹配
列表只有在到达基本大小写时才会被完全绑定,一旦在第二个参数中匹配的术语用完,就会将其绑定到空列表[]
,创建类似[E1,E2,…,En |[]
,其中每个E1
到En
匹配模式;该术语相当于列表[E1,E2,…,En]
按如下方式测试该谓词将给出:
?- filter(foo(X,Y), [a,b,foo(x,y),c(f),foo(v(3),Z),5], L).
L = [foo(x, y), foo(v(3), Z)] ;
false.
请注意,这里所有与模式foo(X,Y)
相统一的内容都会根据需要过滤到L
中
最后一点注意:在您的代码中,调用append(foo(X,Y),R,L)
将始终失败,因为append/3
仅对列表进行操作;您可能想调用append([foo(X,Y)],R,L)
,但在这种情况下,您只需将L=[foo(X,Y)| R]
用作速记
编辑:要匹配您的特定情况,即您有可能匹配和筛选的模式列表,这里有另一个谓词,filter\u list/3
:
filter(_Pattern, [], []).
filter(Pattern, [E|Es], Matches) :-
Pattern \= E, !,
filter(Pattern, Es, Matches).
filter(Pattern, [E|Es], [E|Matches]) :-
filter(Pattern, Es, Matches).
filter_list(_Patterns, [], []).
filter_list(Patterns, [E|Es], Matches) :-
filter(E, Patterns, []), !,
filter_list(Patterns, Es, Matches).
filter_list(Patterns, [E|Es], [E|Matches]) :-
filter_list(Patterns, Es, Matches).
请注意,filter\u list/3
取决于我之前对filter/3
的定义,并且是使用完全相同的策略实现的:如果E
与任何模式
不匹配(即,这是筛选(E,Patterns,[])
成功的情况),那么我们将忘记E
,然后继续,否则(最后一条)我们保留它。测试为我们提供:
?- filter_list([foo(X,Y),bar(X),b], [a,b,foo(X,Y),c], L).
L = [b, foo(X, Y)] ;
false.
在您的示例代码中,除了…append(foo)(…标准的append/3谓词对list.append(foo(任何内容))进行操作外,我不必看父亲,…与它的任何一个子句都不匹配。因此,您的第一个示例子句应该始终失败,第二个示例子句应该失败或开始构建无限多的未绑定变量列表,最终在内存耗尽时崩溃。至于您最终想在这里做什么,我现在还不清楚,但听起来您似乎不想这样做模式匹配,甚至在列表中查找与给定术语统一的项。为什么您认为append/3是一种方法