【问题标题】:Prolog term concatenationProlog 术语连接
【发布时间】:2010-06-10 17:34:47
【问题描述】:

我正在尝试格式化程序的结果,但遇到了困难。

我想给出这样的结果:

Res = do(paint(x) do(clean(a), do(repair(b) , initialState)))

基本上,我想将连续的术语连接到 initialState atom,但是它不适用于 atom_concat,因为要连接的其他术语不是原子,而且我想在每次通过“do”函数时添加 ) .

所以它应该是这样的:Res = initialState.

当 do 函数被调用时,我会有一个类似的函数

concatenateTerm(Pred, Res, Res).

例如 Pred beeing repair(b) 并获取结果:res = do(repair(b),initialState)。

这样可以吗?

谢谢

【问题讨论】:

  • 可能我不明白你的意思,但是......我想你的意思是concatenateTerm(Pred,Res,ResNext)。在这种情况下,将其定义为concatenateTerm(A, B, do(A, B)).
  • 但是 concatenateterm 不会给我 res 结果。我可以执行 Temp = Res,然后调用 concatenateTerm (Pred,Temp, Res),它将 Pred 与 Temp 连接并在 Res 上给出结果,但又一次,它不适用于 atom_concat,因为它因非原子术语而失败。而且它也不会在末尾添加 )。
  • 您想从简单的术语中构建一个复杂的术语?
  • 原子在逻辑上是不能分成更小的部分(这就是为什么“原子”)。 IE。如果您有Steel = combine(carbon, coal),您可以通过combine(X, Y) = Steel 获取超出期限的元素combine(carbon,coal),但您无法获得任何超出期限的元素carbon,因为那是atom。您可以对原子做的唯一事情是尝试将它们与变量统一(有规则atom_chars,但它们是“特殊的”)。
  • 对不起,我错过了对我的答案的评论,我已经评论了。

标签: prolog concatenation


【解决方案1】:

如果我理解正确,您需要执行以下操作:

Res0 = initialState,
do(repair(b), Res0, Res1),
do(clean(a), Res1, Res2),
do(paint(x), Res2, Res3),

您的最终结果在Res3 中。请记住 prolog 过程不会“返回”任何内容,输入和输出值必须通过参数传递。

为什么要将连续的项连接到 atom initialState?这不是序言方式。在 prolog 中构建一个每次都修改的结构会更自然。

【讨论】:

  • 除了 prolog 不会“返回”它也不会“修改”(与动态谓词相关的特殊情况除外,但替换某些谓词也是一种不好的方法)。唯一可以看起来像“修改”(但实际上不是)的是使用部分绑定变量,其中部分变量在某些步骤中可能绑定到另一个部分绑定变量(例如Res3 = do(paint(x), Res2), Res2 = do(clean(a), Res1), Res1 = do(repair(b), Res0), Res0 = initialStatemember((red=blue),X), member((blue=red),X))。但无论如何,在您的示例中,您没有 concatenation 术语,只能调用 do/3
  • @ony 抱歉错过了。当然,还有术语的连接。当do/3 执行任何操作时,它会将更多信息添加到其“输入”项,即第二个参数,并通过将其绑定到其第三个参数来“返回”它。因此绑定到Res0 的值被修改并绑定到Res1,然后修改并绑定到Res2,后者被修改并绑定到Res3。这种通过变量链接的数据在 Prolog 中很常见,变量命名表明了这一点。 Res0 -> Res1 -> Res2 -> Res3
【解决方案2】:

我同意@rvirding 的观点,因为您可能只需要构造一个 PROLOG term 作为结果,而不是尝试构造一个 atom。即使您尝试后者(这确实是可能的),如果需要,您通常可以使用实用函数(例如 SWI-PROLOG 中的 atom_to_term/3term_to_atom/2)将原子转换为术语,然后再转换回来。

不管怎样,一个简单的谓词来获取你的“状态”术语的完整列表并输出你之前描述的这样一个术语可能看起来像这样:

build_do_term([X,Y], do(X,Y)) :- !.
build_do_term([X|Xs], do(X,Rem)) :-
    build_do_term(Xs, Rem).

根据状态项(其中必须至少有两个)调用此谓词:

?- build_do_term([paint(x), clean(a), repair(b), initialState], Rem).
Rem = do(paint(x), do(clean(a), do(repair(b), initialState))).

...这反映了您所描述的行为。如果您不想从列表中一次性构建术语,您仍然可以在自己的代码中使用上面build_do_term/2 中使用的do/2 术语构造方法,根据需要构造适当的do/2 术语。

【讨论】:

  • 你怎么猜到@d0pe 已经在[paint(x) | [clean(a) | [... |[]]..] 列表中concatenated 项,这与do/2concatenation 问题完全相同?
  • 我没有猜测或假设@d0pe 正在使用的代码。此处使用列表结构作为build_do_term/2 的输入的目的是为了以一种简单的方式说明如何实现PROLOG 谓词来构造(假定)必要的do/2 术语,正如所描述的那样,作为指导,因为d0pe 想要类似concatenateTerm/3 的东西。我认为从我在帖子中的最后陈述中可以清楚地看到这一点... :-\
【解决方案3】:

@d0pe,prolog 中没有结果(我猜它们存在于 Mercury 和 Erlang 中)只有命名值在 head 中指定/统一,并且可能稍后在 body 中统一。在大多数情况下执行Temp = Res, concatenateTerm (Pred,Temp, Res) 将失败,因为Temp = Res, Res = do(Pred, Temp) 将产生无限递归项do(Pred, do(Pred, do(Pred, ...)))(当适当的扩展可用时)。我想这不是你想要的。
但现在我明白你想修改 Res - 这是对 Prolog 的错误理解。没有变量,你应该使用下一个方法Res0 = initialState, Res1 = do(repair(b), Res0), Res2 = do(clean(a), Res1), Res3 = do(paint(x), Res2).

您的规则可能类似于(参见序言中的猴子+香蕉示例):

solve(FinalState, finish, FinalState). % our initial state is our goal

solve(InitState, do(Action, Future), FinalState):-
  action(InitState, Action, NewState),
  solve(NewState, Future, FinalState).

【讨论】:

  • 我相信@d0pe 只是问如何构造一个术语格式化一些输出...你为什么(相当混乱)在无限地谈论递归术语和修改绑定变量?
  • @rati,我确实回答了如何构建一个术语。提到递归术语和修改绑定变量是因为“所以它会像:”和Res = initialState, concatenateTerm(Pred, Res, Res), Pred = repair(b) 并期待Res = do(repair(b), initialState) 这看起来像@d0pe concatenateTerm 应该采取“第一个”Res 连接repair(b) 到并将其返回为“第二个”Res.
猜你喜欢
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
相关资源
最近更新 更多