假设,我有一个prolog谓词,如:
name(music,[jazz,blues,classical]).
我想要的是检查爵士乐的会员资格,如果在音乐中,请回复我吗?
到目前为止,我做到了这一点:
ismember(X,Y):-imember(X,name(Y,Z)),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
但它不起作用。
?- ismember(jazz,music).
false.
它并没有写write(Z)
部分。
答案 0 :(得分:4)
在以下片段的可见部分中存在错误。您的程序不仅会失败,而且以下泛化也会失败:
:- op(950, fy, *). *(_). ismember(X,Y):- imember(_/*X*/,name(_/*Y*/,Z)). imember(X,[_|Tail]):- *imember(X,Tail).imember(X,[_/*X*/|_]). ?- ismember(X, Y).
通过用_
替换某些变量,并用*
删除一个目标,获得了泛化。它尽可能概括 。也就是说,任何进一步的概括都会使目标成功。并且有一个很好的属性(纯粹的,单调的)Prolog:
如果泛化失败(对于特定查询),则原始程序也会失败(对于同一查询)。
这是一个很好的属性,它以某种方式确定了通用片段和原始程序之间的因果关系。如果要删除错误,则必须更改通用程序中的某些内容。或者相反:如果您进行的更改仍然允许进行泛化,那么您还没有修复错误。
考虑到这一点,在搜索这样的片段时,不需要“理解”实际的程序。只要这是可能的,只要盲目地猜测和概括就足够了。
现在,如果我们看一下那个概括性说明
ismember/2
的论点完全被忽略了!
答案 1 :(得分:2)
问题是,您在name(Y,Z)
谓词中传递的imember/2
不是列表。你可以简单地写:
ismember(X,Y):-name(Y,Z),imember(X,Z),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
示例:
?- ismember(jazz,music).
[jazz,blues,classical]
true.
答案 2 :(得分:0)
ismember / 2谓词第二个参数是一个列表,而您没有传递列表
这是一个跟踪
[trace] ?- ismember(jazz,music).
Call: (8) ismember(jazz, music) ? creep
Call: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (8) ismember(jazz, music) ? creep
false.
@coder答案是正确的方法
或者你可以简单地使用member / 2谓词,如下所示:
首先在数据库中定义您的列表:
music([jazz,blues,classical]).
现在我们有了音乐类型列表,接下来我们写了规则
ismusicmember(X) :- music(L) , member(X,L),write(L).
music(L)
将变量L指定给我们的音乐列表
member(X,L)
成员/ 2谓词检查X是否在列表中
并运行查询
?- ismusicmember(jazz).
[jazz,blues,classical]
true .
追踪:
[trace] ?- ismusicmember(jazz).
Call: (8) ismusicmember(jazz) ? creep
Call: (9) music(_7376) ? creep
Exit: (9) music([jazz, blues, classical]) ? creep
Call: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Exit: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Call: (9) write([jazz, blues, classical]) ? creep
[jazz,blues,classical]
Exit: (9) write([jazz, blues, classical]) ? creep
Exit: (8) ismusicmember(jazz) ? creep
true .