sistemas - Prolog-sintaxis de contras inusual para listas
reglas en prolog (3)
El operador punto se usó para listas en el primer sistema Prolog de 1972, escrito en Algol-W, a veces llamado Prolog 0. Está inspirado en una notación similar en los sistemas LISP. El siguiente ejemplo es del artículo El nacimiento de Prolog por Alain Colmerauer y Philippe Roussel, los mismos creadores de Prolog.
+ELEMENT(*X, *X.*Y).
+ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).
En ese momento, []
solía ser NIL
.
La siguiente versión de Prolog, escrita en Fortran por Battani & Meloni, usaba casos para distinguir átomos y variables. Luego, DECsystem 10 Prolog introdujo la notación de corchetes reemplazando nil
y X.Xs
con []
y [X,..Xs]
que en versiones posteriores de DECsystem 10 recibieron [X|Xs]
como alternativa. En ISO Prolog, solo hay [X|Xs]
.(X,Xs)
, y como sintaxis canónica ''.''(X,Xs)
.
Tenga en cuenta que el punto tiene muchos roles diferentes en ISO Prolog. Ya sirve como
token final cuando está seguido por un
%
o un carácter de diseño como SPACE, NEWLINE, TAB.Punto decimal en un número de punto flotante, como
3.14159
token gráfico que forma tokens gráficos como
=..
Así que si ahora estás declarando .
Como operador de infijo, hay que tener mucho cuidado. Tanto con lo que escribes como con lo que leerán los sistemas Prolog. Un solo espacio adicional puede cambiar el significado de un término. Considera dos listas de números en ambas notaciones:
[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].
Tenga en cuenta que debe agregar un espacio después de 1
. En este contexto, un espacio en blanco adicional delante de un número puede cambiar el significado de sus términos. Al igual que:
[1|2.3]. [4]. 5. [].
1 .2.3. 4.[]. 5. [].
Aquí hay otro ejemplo que podría ser aún más convincente:
[1,-2].
1.(-2).[].
Los números negativos requieren paréntesis redondos dentro de las listas de puntos.
Hoy en día, solo quedan YAP y XSB que aún ofrecen infijo .
por defecto - y lo hacen de manera diferente . Y XSB ni siquiera reconoce la sintaxis de puntos anterior: necesita corchetes alrededor de algunos de los números no negativos.
Usted escribió que la NHL
parece ser una forma más conveniente de decir [N|[H|L]]
. Existe una regla general para simplificar tales expresiones en ISO Prolog: cada vez que vea dentro de una lista, los tokens |
e [
inmediatamente después de la otra, puede reemplazarlos por ,
(y eliminar el correspondiente ]
en el lado derecho). Así que ahora puedes escribir: [N,H|L]
que no se ve tan mal.
Puedes usar esa regla también en la otra dirección. Si tenemos una lista [1,2,3,4,5]
podemos usar |
como una "hoja de afeitar" así: [1,2,3|[4,5]]
.
Otro comentario, ya que estás leyendo el artículo de Naish: ¡Mientras tanto, se entiende que solo se necesita call/N
! E ISO Prolog admite call/1
, call/2
hasta call/8
.
Me he encontrado con un poco desconocido de la sintaxis de Prolog en la programación lógica de orden superior de Lee Naish en Prolog . Aquí está el primer ejemplo de código del artículo:
% 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).
Mi confusión es con A.As
en isort(A.As, Bs) :-
. Desde el contexto, parece ser una sintaxis de contras alternativa para las listas, el equivalente de isort([A|As], Bs) :-
.
Además, la NHL
parece ser una forma más conveniente de decir [N|[H|L]]
.
Pero SWI Prolog no aceptará esta sintaxis inusual (a menos que esté haciendo algo mal).
¿Alguien lo reconoce? ¿Es mi hipótesis correcta? ¿Qué intérprete de Prolog lo acepta como sintaxis válida?
Esta sintaxis proviene de NU-Prolog. Ver here Probablemente sea solo el funtor normal de la lista ''.'' / 2 redefinido como un operador de infijo, sin la necesidad de una lista vacía al final:
?- 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)
Sí, tienes razón, el punto es el operador infijo de la lista. En realidad es requerido por el estándar ISO Prolog, pero generalmente oculto. Encontré (y usé) esa sintaxis hace algún tiempo:
:- 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 */
Me aconsejaron que no lo hiciera. Efectivamente, la sintaxis [A | B] es una evolución de la. Operador, introducido por legibilidad.
OT : ¿cuál es ese código?
el código de arriba es mi intento de endulzar Prolog con funciones. A saber, introduce a pedido, mediante $
, las variables temporales requeridas (por ejemplo) por expresiones aritméticas
fact(N, F) :-
N > 1 -> F is N * $fact($(N - 1)) ; F is 1.
Cada $ introduce una variable. Después de la expansión, tenemos un hecho más tradicional / 2
?- listing(fact).
plunit_eog:fact(A, C) :-
( A>1
-> B is A+ -1,
fact(B, D),
C is A*D
; C is 1
).
Donde tenemos muchas expresiones, eso podría ser útil ...