我在Lee Naish的论文 Higher-order logic programming in 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).
我对A.As
中的isort(A.As, Bs) :-
感到困惑。从上下文中,出现成为列表的替代cons语法,相当于isort([A|As], Bs) :-
。
同样N.H.L
似乎是一种更方便的方式来说[N|[H|L]]
。
但SWI Prolog不会接受这种不寻常的语法(除非我做错了)。
有人认出来吗?我的假设是正确的吗?哪个Prolog解释器接受它作为有效语法?
答案 0 :(得分:33)
点运算符用于1972年第一个Prolog系统中的列表,用Algol-W编写,有时称为Prolog 0.它的灵感来自LISP系统中的类似符号。以下例子来自Alain Colmerauer和Philippe Roussel的文章The birth of Prolog - Prolog的创作者。
+ELEMENT(*X, *X.*Y).
+ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).
那时,[]
曾是NIL
。
下一个Prolog版本,由Battani&amp;撰写的Fortran编写。 Meloni,用例来区分原子和变量。然后DECsystem 10 Prolog引入了方括号表示法替换nil
和X.Xs
替换[]
和[X,..Xs]
,后者在DECsystem 10的后续版本中接收[X|Xs]
作为替代。在ISO Prolog中,只有[X|Xs]
,.(X,Xs)
和规范语法'.'(X,Xs)
。
请注意,这个圆点在ISO Prolog中有许多不同的角色。它已经服务
结束标记后跟%
或布局字符,如SPACE,NEWLINE,TAB。
小数点的浮点数,如3.14159
图形标记字符将图形标记形成为=..
因此,如果您现在将.
声明为中缀运算符,则必须非常小心。你写的东西和Prolog系统会读到的东西。单个额外空格可以改变术语的含义。考虑两种符号中的两个数字列表:
[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].
请注意,您必须在1
之后添加空格。在这种情况下,数字前面的额外空格可能会改变您的术语的含义。像这样:
[1|2.3]. [4]. 5. [].
1 .2.3. 4.[]. 5. [].
这是另一个可能更有说服力的例子:
[1,-2].
1.(-2).[].
负数需要圆点列表中的圆括号。
今天,只剩下YAP和XSB,默认情况下仍会提供中缀.
- 和they do it differently。并且XSB甚至不识别上面的点语法:你需要围绕一些非负数的圆括号。
您写道,N.H.L
似乎是一种更方便的说[N|[H|L]]
的方式。在ISO Prolog中有一个简单的经验法则来简化这些表达式:每当你在列表中看到标记|
和[
之后,你可以用{{1}替换它们。 (并删除右侧的相应,
)。所以你现在可以写:]
看起来 不好。
您也可以在另一个方向使用该规则。如果我们有一个列表[N,H|L]
,我们可以使用[1,2,3,4,5]
作为“剃刀刀片”,如下所示:|
。
另一个评论,因为你正在阅读Naish的论文:与此同时,well understood只需要[1,2,3|[4,5]]
! ISO Prolog支持call/N
,call/1
最多call/2
。
答案 1 :(得分:10)
是的,你是对的,点是列表 cons 中缀运算符。它实际上是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 */
我被告知反对它。实际上,[A | B]语法是它的演变。为了便于阅读而引入的操作符。
OT :那段代码是什么?
上面的代码是我尝试用功能使Prolog变甜的尝试。即,通过$
引入请求,通过算术表达式(例如)所需的临时变量
fact(N, F) :-
N > 1 -> F is N * $fact($(N - 1)) ; F is 1.
每个$引入一个变量。扩张后,我们有一个更传统的事实/ 2
?- listing(fact).
plunit_eog:fact(A, C) :-
( A>1
-> B is A+ -1,
fact(B, D),
C is A*D
; C is 1
).
我们有很多表达方式,这可能很有用......
答案 2 :(得分:9)
此语法来自NU-Prolog。见here。它可能只是普通的列表仿函数'。'/ 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)