【问题标题】:Prolog if/else statement with recursion带有递归的 Prolog if/else 语句
【发布时间】:2013-02-22 02:23:31
【问题描述】:

我是 prolog 的新手,我正在尝试弄清楚如何使用 if/else 语句和递归。为了说明,我编写了一个简单的 prolog 程序。该程序是无用的(因为它的功能是无用的),但它帮助我说明我的问题。程序获取一个列表,检查列表的头部,看看它是否是最后一个元素;如果不是,它将头部添加到临时列表变量中,并使用列表的尾部以递归方式运行程序。它应该在最后输出列表。程序:

 gothrough([H|T], B, C):-
      append(B,H,B),
      (  (T == [])
      -> C=B
      ;  gothrough(T, B, C)
      ).

来电:gothrough([sample, phrase, here], [], C).

预期输出:C = [sample, phrase, here]

当前输出:no

对我做错了什么有帮助吗?

谢谢!

【问题讨论】:

  • append 的所有参数都应该是列表,只有当 H 是空列表时,append(B, H, B) 才能成功。看这段代码,很难理解为什么你认为 C 最终会等于第一个参数,或者 B 将要做什么,所以我认为你有比递归更深层次的问题。
  • 你说得对……我简化了程序,我忘了设置 C 等于 B。但是你能详细说明一下 H 是空列表吗?我以为append将B和H的内容附加到B中。例如,如果B = [昨天]和H = [今天],那么append(B, H, B) = [昨天,今天]?

标签: if-statement recursion prolog


【解决方案1】:

从您的 cmets 中,我了解到您误解了 append(以及一般的 Prolog)的工作原理。

这根本不是真的:“如果 B = [昨天] 和 H = [今天],那么 append(B, H, B) = [昨天,今天]”。

append(B, H, B) 表示“将 H 附加到 B 再次生成 B”。这只有在 H 是一个空列表时才有可能。

要理解的关键是append(B, H, B) 中的两个 B 是相同的,它们必须具有相同的值。这就像代数中的变量 - 方程中的所有 X 表示相同的值。

您应该为输出变量使用不同的名称,例如 append(B, H, Bnew) - 这样会更有意义。

【讨论】:

    【解决方案2】:

    第一个问题是append(B, H, B),这对于大多数输入没有意义。

    第二个问题是 if-then-else 的结果和替代,即->; 之后的部分必须都是 Prolog 目标(语句)。 C 不是目标。你的意思可能是C=B,虽然很难说,因为我很难理解你的程序在做什么。

    【讨论】:

    • 感谢您的评论,是的,您完全正确。我简化了我的原始程序,但我忘记将 C 设置为 B。所以我在原始帖子中对其进行了编辑。但我很困惑为什么append(B, H, B) 对大多数输入没有意义?
    【解决方案3】:

    你得到一个否定,因为 append(B,H,B) 失败,除非 H 是 [];请记住,这些是从句,而不是赋值。而且由于您从不将任何内容绑定到 C,因此如果您的陈述被证明,它将永远不会有任何价值。

    这将完成你的任务:

    gothrough([],L,L).
    gothrough([H|T], B, C) :- gothrough(T,B,Cx), append([H],Cx,C).
    

    【讨论】:

    • 感谢您的评论!您能否详细说明为什么append(B,H,B) 需要失败,除非 B 是 []?我想如果 B = [昨天] 和 H = [今天],那么 append(B, H, B) = [昨天,今天]?
    • @pauliwago 在 Prolog 中,变量只有一个绑定,并且函数不会“返回”,因此您所说的根本不适用于 Prolog。我建议你回去从头开始。
    • append(B,H,B) 失败,除非 H 是 [],而不是 B。
    【解决方案4】:

    这可以更简单地完成:

    gothrough([], []).
    gothrough([H|T], [H|X]) :-
        gothrough(T, X).
    

    第一个规则匹配您的空列表条件,然后强制递归结束/要构建的列表。

    第二条规则匹配除空列表之外的所有内容,在这种情况下,头部 H 被附加到 X 上,其中 X 是通过递归尾部获得的列表的结果。 IE。您不需要使用 append 谓词 - prolog 中内置了列表追加。

    ?- gothrough([simple, phrase, here], X).
    X = [simple, phrase, here].
    

    这个解决方案也少了一个变量。

    【讨论】:

      最近更新 更多