【问题标题】:Prolog, building list with conditional clausesProlog,带有条件子句的构建列表
【发布时间】:2011-05-16 21:34:00
【问题描述】:

我需要使用 prolog(SWI 风格)来完成这项家庭作业,并且无法理解某些事情。

例如,如果我想遍历一个列表并将其元素添加到另一个列表中,但只有当它们满足特定条件时,我将如何处理它?我可以将它们全部添加,也可以不添加,但是如果我添加检查此条件的子句,则整个递归结果为“假”。我明白为什么会这样,但不知道如何解决它。基本上我想要的是:

goal(Stuff) :- do_something(X),
               only_do_this_if_something(Y),
               always_do_this(Z).

目前,如果only_do_this_if_something(Y) 失败,always_do_this(Z) 也不会发生,因为整个目标都变为错误...

【问题讨论】:

标签: if-statement prolog conditional


【解决方案1】:

你可以使用 if 结构:

<condition> -> (do_something) ; (do_something else)

在这种情况下:

goal(Stuff):-
  do_something(X),
  if_something(Y)-> do_this(Y) ; true,
  always_do_this(Z).

或者您只需编写两个子句,例如:

goal(Stuff):-
  do_something(X),
  conditional_stuff(Y),
  always_do_this(Z).

conditional_stuff(Y):-
  condition(Y),
  do_this(Y).

conditional_stuff(_).

【讨论】:

  • 谢谢,这条消息的第一部分很好地解决了这个问题。
【解决方案2】:

检查以下编程模式,它在 Prolog 中使用得非常多:

  • 遍历列表,一次一个元素
  • 为递归设置基本情况
  • 在一个子句中,检查条件是否适用并做某事,然后继续递归
  • 在下一个子句中跳过该项目并继续递归

您必须使用剪切 (!) 来禁止回溯,或者明确检查该条件是否不适用于后一个子句。

请注意,您说您想要一个输出列表,其中包含应用了“某事”的项目(这不是您在代码中编写的内容)...

将此模式应用于您的问题,它看起来像这样:

myRecursion([], []). % This is the base case
myRecursion([Item|Tail], [Item|NTail]):-
  something_applies(...),
  do_something(...),
  only_do_this_if_something(...),
  always_do_this(...).
  myRecursion(Tail, NTail).
myRecursion([Item|Tail], NTail):-
  not(something_applies(...)),
  do_something(...),
  always_do_this(...),
  myRecursion(Tail, NTail).

【讨论】:

  • -1。由于重复,这很复杂且容易出错,并且完全没有必要,因为 Prolog 有一个 if-then-else 结构。
  • 我完全不同意你的观点;)我相信为不同的行为设置不同的条款会更清楚。每个子句正文的第一部分区分不同的情况,然后您只需在该子句的其余部分执行您想做的任何事情。试着用几个 if-then-else 结构来理解一段代码,我相信你可能会同意我的观点。但是,如果不影响可读性,可以在这里和那里使用一些 if-then-else。
  • 我经常使用 if-then-else 结构,发现它对我的代码的清晰速度有很大贡献。它的逻辑含义比cut更清晰,而它与你的风格相比保持了DRY原则。
【解决方案3】:

如果我理解正确,那么您需要的是像include/3 这样的谓词:

include(:Goal, +List1, ?List2)
    Filter elements for which Goal succeeds. True if List2 contains
    those elements Xi of List1 for which call(Goal, Xi) succeeds.

使用示例:

?- include(number, [a(b), 2, _, 1.2, C, '1'], L).
L = [2, 1.2].

现在你的作业变成了“如何实现include/3”。一旦你实现了 include/3 的版本,你可以通过查看它的源代码来检查它是否与 SWI 的版本匹配:listing(include)

【讨论】:

    【解决方案4】:

    尝试忽略/1 谓词:

    goal(Stuff) :-
        do_something(X)
        ignore(only_do_this_if_something(Y)),
        always_do_this(Z).
    

    ignore/1 调用唯一的参数,无论失败与否都成功:

    ignore(X) :- X, !.
    ignore(_).
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      相关资源
      最近更新 更多