好的Prolog代码的特性?

好的Prolog代码的特性?,prolog,failure-slice,logical-purity,clpfd,Prolog,Failure Slice,Logical Purity,Clpfd,要写出好的序言,需要掌握哪些设计启发法?我听说一个有经验的程序员需要两年左右的时间才能精通Prolog。有效地使用递归是其中的一部分,但这似乎是一个相对较小的障碍。到底是什么给程序员带来了这么多麻烦?我应该在示例代码中寻找什么来判断其质量?编写好的Prolog代码的主要困难不仅在于理解,而且在于充分传达程序的意图或目的。与其他编程语言不同的是,同一个程序中通常有几种完全不同的Prolog代码。混淆这些级别会导致错误和问题: 纯单调代码。 这段代码是Prolog的核心。在这样的代码中,有很多代数性

要写出好的序言,需要掌握哪些设计启发法?我听说一个有经验的程序员需要两年左右的时间才能精通Prolog。有效地使用递归是其中的一部分,但这似乎是一个相对较小的障碍。到底是什么给程序员带来了这么多麻烦?我应该在示例代码中寻找什么来判断其质量?

编写好的Prolog代码的主要困难不仅在于理解,而且在于充分传达程序的意图或目的。与其他编程语言不同的是,同一个程序中通常有几种完全不同的Prolog代码。混淆这些级别会导致错误和问题:

纯单调代码。 这段代码是Prolog的核心。在这样的代码中,有很多代数性质,实际问题是用纯的、理想的方式描述的,Prolog经常用这种方式宣传。然而,即使在这些部分,某些程序属性也可能出现,例如非终止性。以连词的交换性为例。在纯单调代码中,
(A,B)
(B,A)
描述了相同的关系。唯一的区别可能在于不同的终止行为和答案出现的顺序。理想情况下,纯谓词的名称表示谓词是关系。在这里,命令绝对不是一个好的选择

副作用代码。 另一个极端是代码,只有通过机器或头脑有效地执行它才能理解代码。程序中没有简单的不变量。但即使在这些部件中,仍可能观察到某些特性,如稳定性。实际上,这样的代码与其他编程语言没有太大区别

通常,副作用部分“吞噬”了纯粹的一面,因为程序员习惯于命令式的、面向命令的“做这个做那个”的思维。要向另一个方向倾斜,请考虑您将失去或获得哪些属性。想想测试你的程序有多容易:一个程序越纯,在没有任何额外沙箱的情况下测试就越容易。一个简单的顶级查询就足够了

例如,如何以看似必要的副作用为代价扩大纯副作用:

或者干脆

编辑:在你的评论中,你要求“学习建议”。以下是一些:

  • 坚持只编写纯粹、单调的代码。你只能选择一方或另一方,如果你两者都知道的话。我假设您以前在一些面向命令的语言中有过产生副作用的经验,但在纯代码中没有。因此,这将意味着您将避免编写固有的非单调代码

  • 玩顶级游戏。想象一下,顶层是访问程序的唯一途径。您将如何制定一个问题,使其符合此格式?SWI toplevel经过专门设计,可实现这种轻量级交互

  • 用于算术。不要使用
    (is)/2
    ,这会使您的代码过于陈旧

  • 享受纯单调代码的代数性质。想一想:你添加了一个目标,无论在哪里,你仍然可以预测这个目标将专门化你的程序(最好保持原样)。你可以盲目地取消一个目标,但你仍然知道它的影响(部分)

  • 学习a的概念,掌握不终止

  • 不要使用循序渐进的跟踪程序/调试器,因为许多序言中都提供了它。它只显示Prolog所采取的精确步骤。它不会向您显示任何与程序含义直接相关的内容。它强化了一步一步的思考

  • 注意你的语言。你谈论一个节目的方式会影响你思考它的方式。因此,如果您使用大量的操作化语言(如:This-does-This等),那么您很可能会强化面向命令的视图。有一种更干净的方式来谈论事情,但你需要找到它。这可能是最难的部分


  • 你是说主要的困难是知道什么时候用命令式或声明式的方式来处理特定的子问题?我希望这些知识来自于对特定系统和特定问题的大量经验。所以我猜你不能给出多少关于学习的一般性建议。@user287424:我提出了一个问题:你会失去或获得多少财产?测试代码有多容易?这可能是对你的回答,虽然这需要一些时间来详细考虑。经验当然使这更容易、更快,但你可以从这开始。@j4nbur53单调性和稳定性并不总是相关的。以
    append/3
    的第一个参数为例:它不是稳定的,但定义仍然是单调的。@j4nbur53:您在评论“学习建议”。没有议程。如果你需要一个大的领域来证明你的观点,那就拿:
    7^7^7#>=abs(X)
    作为两年的目标——这甚至与Prolog无关!