If statement Prolog,带条件子句的生成列表

If statement Prolog,带条件子句的生成列表,if-statement,prolog,conditional,If Statement,Prolog,Conditional,我需要用prolog(SWI-flavor)来做这个家庭作业,但有些事情我不能动脑 例如,如果我想遍历一个列表并将其元素添加到另一个列表中,但仅当它们满足特定条件时,我该怎么做?我可以将它们全部添加,也可以不添加,但如果我添加检查此条件的子句,整个递归结果将是“false”。我理解这是为什么,但不知道如何解决它。基本上我想要的是: goal(Stuff) :- do_something(X), only_do_this_if_something(Y),

我需要用prolog(SWI-flavor)来做这个家庭作业,但有些事情我不能动脑

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

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

当前,如果
只有当某个(Y)
失败时才执行此操作,那么
始终执行此操作(Z)
不会发生,因为整个目标变为false…

尝试忽略/1谓词:

goal(Stuff) :-
    do_something(X)
    ignore(only_do_this_if_something(Y)),
    always_do_this(Z).
ignore/1调用唯一的参数,无论是否失败,都会成功:

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

您可以使用if结构:

<condition> -> (do_something) ; (do_something else)
或者你只需写两个条款,如:

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

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

conditional_stuff(_).

检查以下编程模式,这在Prolog中被大量使用:

  • 遍历列表,一次遍历一个元素
  • 为递归设置基本情况
  • 在一个子句中,检查条件是否适用并执行某些操作,然后继续递归
  • 在下一个子句中,跳过该项并继续递归
您必须使用cut(!)来禁止回溯,或者明确检查后一条款中的条件是否不适用

请注意,您说过希望有一个输出列表,其中包含应用了“某物”的项(这不是您在代码中编写的内容)

将此模式应用到您的问题中,它将如下所示:

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).

如果我理解正确,那么您需要的是一个谓词,如
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)

+1诚实地告诉你家庭作业需要帮助。@GuyC的可能重复:这里没有特定于SWI的内容-1.由于重复,这很复杂,而且容易出现错误,而且完全没有必要,因为Prolog有一个if-then-else构造我认为,为单独的行动制定单独的条款要清楚得多。每一个条款正文的第一部分区分不同的情况,然后你只需要在条款的其余部分做你想做的事情。尝试用if-then-else结构来理解一段代码,我相信您可能会同意我的观点。但是,在不影响可读性的情况下,到处使用if-then-else是可以的。我经常使用if-then-else结构,发现它大大提高了代码的清晰度和速度。它的逻辑意义比cut更清晰,同时与你的风格相比,它保持了干燥的原则。谢谢,本文的第一部分很好地解决了这个问题。
?- include(number, [a(b), 2, _, 1.2, C, '1'], L).
L = [2, 1.2].