【问题标题】:I want to write a sublist rule but SWI-Prolog doesn't make it past rule declaration line我想写一个子列表规则,但 SWI-Prolog 没有使它超过规则声明行
【发布时间】:2020-05-21 17:20:18
【问题描述】:

我是 Prolog 的新手,我想创建一个规则,该规则采用这种格式 [(X,Y,Z)|Tail] 的列表,并仅使用 Y 来创建一个新列表。我写了这个,但编译器没有让它超过规则声明行。我这样做是不是错误的方式?

sublist([], []).
sublist([Phead | (_,Membro,_)], [Lhead | Ltail]) :-
    Ltail is Membro,
    sublist(Phead, Lhead).

【问题讨论】:

  • 这至少在语法上是有效的。编译器到底说了什么?
  • 显然您正在使用is/2,它用于以命令式编程中的赋值运算符的方式进行算术评估。大不。还要考虑一下为什么 Ltail := Membro 考虑到您的问题陈述绝对没有意义。
  • 使用跟踪功能,我可以看到它在运行此行时返回 false: sublist([Phead | (,Membro,)], [Lhead | Ltail]) :- 我在编译器中写了这一行: sublist([(start, beijing, 0), (train,hong_kong, 13), (bus,bombay,23)],City_list)
  • 你是不是想说 Ltail=Membro 也没有意义?顺便说一句,谢谢您的回复!

标签: prolog


【解决方案1】:

此代码需要一些更改。

我们如何关联“输入列表”和“输出列表”来满足规范?

我们很幸运,因为规范允许我们将“输入列表”(左)和“输出列表”(右)中的元素一对一关联,因此:

sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
   relate_element(LeftHead, RightHead),
   relate_lists(LeftTail, RightTail).

关联没有当前头的尾部与关联任何列表相同,因此:

sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
   relate_element(LeftHead, RightHead),
   sublist(LeftTail, RightTail).

左侧的空列表与右侧的空列表相关,因此基本情况是(正确):

sublist([], []).

基本情况不能与“正常”情况混淆,因为头部 sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :- 中的参数与空列表不匹配,因此无需在基本和常规的子句主体中添加任何额外检查将它们分开。不错。

现在,relate_element(LeftHead, RightHead) 呢?

让我们编程出relate_element(LeftHead, RightHead) :- ....

规范说“左头”的形式是(X,Y,Z)(这是不好的形式,最好是[X,Y,Z],但让那只狗躺着吧)。

所以我们只对匹配 LeftHead 的调用感兴趣:

relate_element((X,Y,Z), RightHead) :- ...

规范说RightHead 应该只是Y。好的!

relate_element((X,Y,Z), Y) :- ...

当获得与头参数匹配时,正文中会发生什么?好吧,没什么,只是成功。

relate_element((X,Y,Z), Y) :- true.

简化为

relate_element((X,Y,Z), Y).

我们的计划:

sublist([], []).
sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
   relate_element(LeftHead, RightHead),
   sublist(LeftTail, RightTail).

relate_element((X,Y,Z), Y).

但您也可以声明LeftHead 从一开始就必须是(X,Y,Z),类似于RightHeadY。因此

sublist([], []).
sublist( [ (X,Y,Z) | LeftTail ] , [ Y | RightTail ] ) :-
   relate_element((X,Y,Z), Y),
   sublist(LeftTail, RightTail).

relate_element((X,Y,Z), Y).

relate_element/2 现在什么都不做,所以让我们简化(并用_ 标记单例变量):

sublist([], []).
sublist( [ (_X,Y,_Z) | LeftTail ] , [ Y | RightTail ] ) :-
   sublist(LeftTail, RightTail).

有效吗?以plunit为例,我们来看看正确的事情是否确实相关,而错误的事情是否不相关:

:- begin_tests(sublist).

test(one) :- sublist([],[]).
test(two) :- sublist([(a,b,c),(e,f,g),(h,i,j)],[b,f,i]).
test(three,fail) :- sublist([(a,b,c),(1,2),(h,i,j)],_).
test(four,fail)  :- sublist([(a,b,c),(e,f,g),(h,i,j)],[b,x,i]).
test(five,fail)  :- sublist([(a,b,c),(e,f,g),(h,i,j)],[]).

:- end_tests(sublist).

rt(sublist) :- run_tests(sublist).

然后

?- rt(_X).
% PL-Unit: sublist ..... done
% All 5 tests passed
_X = sublist.

您也可以测试谓词是否“向后”工作。确实如此,为输入发出“模板”:

?- sublist(X,[b,f,i]).
X = [(_10626, b, _10634),  (_10644, f, _10652),  (_10662, i, _10670)].

【讨论】:

  • 非常感谢您!这是一种很奇怪的语言,很难适应,看到你的思维过程来达到这个最终目标真的很有帮助。非常有趣的是,对于如此复杂的思考过程,我们只得到两三行代码。我想这就是 Prolog 的美妙之处 :)
  • @JoãoVaz 很高兴能提供帮助。请不要忘记“接受答案”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多