【问题标题】:About Prolog syntax关于 Prolog 语法
【发布时间】:2013-10-10 17:28:58
【问题描述】:

有时我会看到以下术语: X = a:b 或者 X = a-b

我可以做类似的请求 X = Y:Z 正如预期的那样,编译器将 Y 与 a 和 Z 与 b 统一起来。

现在我的答案是: 我可以使用哪些字符(或字符序列)来组合两个 Prolog 原子?!

也许你可以给我一些关于这个问题的更多信息的链接。

感谢您的帮助和来自德国的亲切问候

【问题讨论】:

    标签: prolog iso-prolog


    【解决方案1】:

    我可以使用哪些字符(或字符序列)来组合两个 Prolog 原子?!

    您在这里要求的是 Prolog 的整个运算符语法定义。要获得此问题的完整答案,请参阅the tag iso-prolog 了解如何获取 Prolog 标准 ISO/IEC 13211-1 的完整信息。

    但作为一个简短的答案开始:

    Prolog 语法包括

    1. 函数符号,如+(a,b),加号

    2. 动态可重新定义的运算符语法,加上

    3. 一些额外的。

    您似乎想知道哪些“字符”可以用作运算符。

    简短的回答是您可以使用所有原子Op 成功用于current_op(Pri,Fix,Op)。因此,您可以动态询问存在哪些运算符:

    ?- current_op(Pri, Fix, Op). 普里 = 1, 修复 = fx, 操作 = ($) ; 普里 = 1150, 修复 = fx, Op = (module_transparent) ; 普里 = 700, 修复 = xfx, 操作 = (=@=) ; 普里 = 700, 修复 = xfx, 操作 = (@>=) ; 普里 = 700, 修复 = xfx, 操作 = (>=) ...

    所有这些运算符都可以以指定的方式使用,作为具有指定优先级的前、中或后缀。其中一些运算符是特定于 SWI 的,有些是由标准定义的。以上,只有@>=>= 是标准运算符。

    大多数运算符仅由图形字符#$&*+-./:<=>?@^~ 或以小写字母开头的字母、数字和下划线组成。有两个单独的字符!;,然后是,|,它们更加特别。与上述不同的运算符名称需要引用 - 您很少会遇到它们。

    要查看运算符如何嵌套,请使用write_canonical(Term)

    长答案是您也可以自己定义此类运算符。但是,请注意,更改运算符语法通常会产生许多难以理解的含义。更重要的是,因为许多系统在一些很少使用的配置上有所不同。比如你提到的系统,SWI differs in several ways

    我建议在您了解更多有关 Prolog 语言的信息之前避免定义新的运算符。

    【讨论】:

      【解决方案2】:

      让我们看看X = Y:Z里面有什么

      ?- display( X = Y:Z ).
      =(_G3,:(_G1,_G2))
      true.
      

      然后我们有一个嵌套结构,其中函子是运算符。

      操作符是一个原子,原子语法规则说我们有 3 种需要考虑:

      • 用单引号括起来的任意可打印字符序列
      • 特殊字符序列,其中特殊字符是 `.=:-+*/>this page你可以检查我是否忘记了某人!)
      • 一系列小写/大写字符或下划线,以小写字符开头

      编辑

      A functor(我认为是函数构造函数的简写,但函数在 Prolog 上下文中具有误导性)它是“绑定”多个参数的符号。参数的数量被命名为 arity。在 Prolog 中,术语是原子文字(如数字或原子), 是递归结构,由 functor 和多个参数组成,每个参数都是术语本身(至少 1 个)。

      给定适当的声明,即 op/3,一元和二元项可以表示为 表达式,就像您展示的那样。

      使用 : 特殊字符的运算符示例是 ':-'

      member(X,[X|_]).
      member(X,[_|T]) :- member(X, T).
      

      【讨论】:

      • 要在不使用运算符语法的情况下查看术语结构的更便携的解决方案,您可以使用 ISO Prolog 标准 write_canonical/1 谓词。
      • 谢谢保罗,你是对的。我熟悉使用 write_canonical/1,就在今天早上(或昨天?)我注意到 Jan 使用了 display/1,我不知道。它比 write_canonical 更容易记住...
      • 首先,感谢您提供的非常有用的 cmets!他们帮了我很多!如果我理解正确,“:”字符是上面示例中的函子?!在这种情况下,函子(究竟什么是函子?!)是运算符,或者??现在还有一个问题:除了“:”之外,我还允许使用哪些其他字符,就像示例中一样。
      • : 不是您所写的“特殊”字符。它是一个图形字符,如#$&*+-./:<=>?@^~
      • 运算符有很多“特殊”字符
      【解决方案3】:

      O.P. 说(我引用):

      有时我会看到类似这样的术语:X = a:bX = a-b

      我可以执行X = Y:Z 之类的请求,并且编译器将 Y 与 a 和 Z 与 b 统一起来,正如预期的那样。

      现在我的答案是:我允许使用哪些字符(或字符序列) 用来组合两个 Prolog 原子?!

      简短的回答是几乎是你想要的任何东西(只要它是一个原子)

      更长的答案是这样的:

      看到的是中缀 (x infix_op b)、前缀 (pfx_op b) 和后缀 (b sfx_op)运算符。任何元数为 2 的结构都可以是中缀运算符。任何元数为 1 的结构都可以是前缀或后缀运算符。因此,任何原子都可以是运算符。

      Prolog 是通过优先驱动的递归下降解析器(自然是用 Prolog 编写的)解析的。在operator/3 谓词中定义和枚举运算符,以及它们的优先级和关联性。关联性与解析树的构造方式有关。像a - b - c 这样的表达式可以解析为( a - ( b - c ) )(右关联)或( ( a - b ) - c )(左关联)。

      优先级与 紧密 运算符的绑定方式有关。像a + b * c 这样的表达式绑定为( a + ( b * c ) 不是因为关联性,而是因为'*'/2(乘法)比'+'/2(加法)具有更高的优先级。

      您可以随心所欲地添加、删除和更改运算符。并不是说这会给你很大的空间来打破 prolog 的语法。

      需要注意的是,任何操作符表达式也可以用普通的符号来写:

      a + b * c
      

      完全相同

      '+'( a , '*'(b,c) )
      

      【讨论】:

      • 没有理由在+(a, *(b,c)) 中引用+*
      • 引用原子并没有什么坏处,它可以提高理解力。 functor/arity 是表示谓词或结构名称和 arity 的常规方式,如 'foo/2'。这不是序言语法:'*'/2 表示“名为 * 的谓词或结构,数量为 2。
      • 当函子是运算符时,标准方法是写括号。正如我所指出的。引用曾经是(大约 30 年前)禁用运算符的约定,但它从未流行起来。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多