Prolog - 列表的不寻常利弊语法

Nic*_*son 27 prolog iso-prolog

我在Lee Naish的论文"Prolog中的高阶逻辑编程"中遇到了一些不熟悉的Prolog语法.以下是本文的第一个代码示例:

% insertion sort (simple version)
isort([], []).
isort(A.As, Bs) :-
    isort(As, Bs1),
    isort(A, Bs1, Bs).

% insert number into sorted list
insert(N, [], [N]).
insert(N, H.L, N.H.L) :-
    N =< H.
insert(N, H.LO, H.L) :-
    N > H,
    insert(N, LO, L).
Run Code Online (Sandbox Code Playgroud)

我的困惑是A.Asisort(A.As, Bs) :-.从上下文来看,它似乎是列表的替代cons语法,相当于isort([A|As], Bs) :-.

N.H.L似乎是一个更方便的方式来表达[N|[H|L]].

但SWI Prolog不接受这种不寻常的语法(除非我做错了).

有谁认出来了吗?我的假设是正确的吗?哪个Prolog解释器接受它作为有效语法?

fal*_*lse 33

点运算符用于1972年第一个Prolog系统中的列表,用Algol-W编写,有时称为Prolog 0.它的灵感来自LISP系统中的类似符号.下面的例子来自Alain Colmerauer和Philippe Roussel 的Prolog诞生 - Prolog的创造者.

+ELEMENT(*X, *X.*Y).
+ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).
Run Code Online (Sandbox Code Playgroud)

那个时候,[]曾经是NIL.

由Battani&Meloni用Fortran编写的下一个Prolog版本使用案例来区分原子和变量.然后DECsystem 10的Prolog引入的方括号替换nilX.Xs[][X,..Xs]其在DECsystem 10的更高版本接收[X|Xs]作为替代.在ISO Prolog的,只存在[X|Xs],.(X,Xs)以及作为典型的语法'.'(X,Xs).

请注意,这个圆点在ISO Prolog中有许多不同的颜色.它已经服务了

  • 结束标记后跟一个%或一个布局字符,如SPACE,NEWLINE,TAB.

  • 浮点数中的小数点,如3.14159

  • 图形标记char形成图形标记为=..

因此,如果您现在宣布.为中缀运算符,则必须非常小心.你写的东西和Prolog系统会读到的东西.单个额外空格可以改变术语的含义.考虑两种符号中的两个数字列表:

[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].
Run Code Online (Sandbox Code Playgroud)

请注意,您必须在之后添加空格1.在这种情况下,数字前面的额外空格可能会改变您的术语的含义.像这样:

[1|2.3]. [4]. 5. [].
1 .2.3. 4.[]. 5. [].
Run Code Online (Sandbox Code Playgroud)

这是另一个可能更有说服力的例子:

[1,-2].
1.(-2).[].
Run Code Online (Sandbox Code Playgroud)

负数需要圆点列表中的圆括号.

今天,只剩下YAP和XSB,.默认情况下仍然提供中缀- 而且他们的做法不同.并且XSB甚至不识别上面的点语法:你需要围绕一些非负数的圆括号.

你写的这N.H.L似乎是一种更方便的说法[N|[H|L]].在ISO Prolog中有一个简单的经验法则来简化这样的表达式:每当你在列表中看到令牌|并且[紧接着彼此之后,你可以用它们替换它们,(并删除]右侧的相应对象).所以你现在可以写:[N,H|L]看起来不那么糟糕.

您也可以在另一个方向上使用该规则.如果我们有一个列表,[1,2,3,4,5]我们就可以|像"剃刀刀片"一样使用: [1,2,3|[4,5]].


另一个评论,因为你正在阅读Naish的论文:与此同时,人们很清楚call/N需要它!并且ISO Prolog支持call/1,call/2最多call/8.

  • 哇,这是一个彻底的答案,非常感谢!`[N,H | L]`确实更好,我不知道它是否有效.我也很欣赏指向该交换的指针,这非常有趣. (4认同)
  • 你可能有兴趣看看[lambdas如何适应`call/N`](http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord). (4认同)
  • 我刚刚检查过,虚线对出现在mccarthy关于lisp的第一篇论文中 - http://www.cs.unm.edu/~luger/cs451/resources/recursive.pdf(第3节) (3认同)
  • 啊,很好,我当时就告诉你了。:) 你有两个选择(但我不是律师):添加另一个答案或在进行另一个编辑后标记你的答案并要求版主将其取消社区维基。但这是一种极端的手段(出于同样的原因,我曾经这样做过)。或者你可以在meta上询问这个问题。:) (2认同)

Cap*_*liC 10

是的,你说得对,点它的列表利弊缀操作符.它实际上是ISO Prolog标准所要求的,但通常是隐藏的.我不久前发现(并使用过)这种语法:

:- module(eog, []).
:- op(103, xfy, (.)).

% where $ARGS appears as argument, replace the call ($ARGS) with a VAR
% the calle goes before caller, binding the VAR (added as last ARG)
funcs(X, (V, Y)) :-
    nonvar(X),
    X =.. W.As,

    % identify meta arguments
    (   predicate_property(X, meta_predicate M)
        % explicitly exclude to handle test(dcg)
        % I'd like to handle this case in general way...
    ,   M \= phrase(2, ?, ?)
    ->  M =.. W.Ms
    ;   true
    ),

    seek_call(As, Ms, Bs, V),
    Y =.. W.Bs.

% look for first $ usage
seek_call([], [], _Bs, _V) :-
    !, fail.
seek_call(A.As, M.Ms, A.Bs, V) :-
    M @>= 0, M @=< 9, % skip meta arguments
    !, seek_call(As, Ms, Bs, V).
seek_call(A.As, _, B.As, V) :-
    nonvar(A),
    A = $(F),
    F =.. Fp.FAs,
    (   current_arithmetic_function(F) % inline arith
    ->  V = (PH is F)
    ;   append(FAs, [PH], FBs),
        V =.. Fp.FBs
    ),
    !, B = PH.
seek_call(A.As, _.Ms, B.As, V) :-
    nonvar(A),
    A =.. F.FAs,
    seek_call(FAs, Ms, FBs, V),
    !, B =.. F.FBs.
seek_call(A.As, _.Ms, A.Bs, V) :-
    !, seek_call(As, Ms, Bs, V).

:- multifile user:goal_expansion/2.
user:goal_expansion(X, Y) :-
    ( X = (_ , _) ; X = (_ ; _) ; X = (_ -> _) )
    -> !, fail % leave control flow unchanged (useless after the meta... handling?)
    ;  funcs(X, Y).

/* end eog.pl */
Run Code Online (Sandbox Code Playgroud)

我被告知反对它.实际上,[A | B]语法是它的演变.为了可读性而引入的运算符.

OT:那段代码是什么?

上面的代码是我试图用功能使Prolog变甜的尝试.即,$通过算术表达式(例如)通过请求引入临时变量

fact(N, F) :-
     N > 1 -> F is N * $fact($(N - 1)) ; F is 1.
Run Code Online (Sandbox Code Playgroud)

每个$引入一个变量.扩张后,我们有一个更传统的事实/ 2

?- listing(fact).
plunit_eog:fact(A, C) :-
    (   A>1
    ->  B is A+ -1,
        fact(B, D),
        C is A*D
    ;   C is 1
    ).
Run Code Online (Sandbox Code Playgroud)

我们有很多表达式,这可能有用......

  • @chac:系统仍然会在发布到发布的基础上改变它们的"goal_expansion/2"之类的含义.这实际上是不可能标准化的. (2认同)

twi*_*rer 9

此语法来自NU-Prolog.看到这里.它可能只是普通的列表仿函数'.'/ 2重新定义为中缀运算符,而不需要一个尾随的空列表:

?- L= .(a,.(b,[])).
L = [a,b]
Yes (0.00s cpu)
?- op(500, xfy, '.').
Yes (0.00s cpu)
?- L = a.b.[].
L = [a,b]
Yes (0.00s cpu)
Run Code Online (Sandbox Code Playgroud)

  • 语法比NU(1987)或MU要老得多. (4认同)