Prolog-sintaxis de contras inusuales para listas


Me he encontrado con un poco desconocido de sintaxis Prolog en el documento de Lee Naish Programación lógica de orden superior en Prolog. Aquí está el primer ejemplo de código del documento:

% 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 está con A.As en isort(A.As, Bs) :-. Desde el contexto, aparece como una sintaxis cons alternativa para listas, el equivalente de isort([A|As], Bs) :-.

También N.H.L 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 correcta mi hipótesis? ¿Qué intérprete de Prolog acepta eso como sintaxis válida?

Author: false, 2012-04-05

3 answers

El operador dot fue usado para listas en el primer sistema Prolog de 1972, escrito en Algol-W, a veces llamado Prolog 0. Está inspirado en notación similar en sistemas LISP. El siguiente ejemplo es del documento The birth of Prolog de 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 del Prolog, escrita en Fortran por Battani & Meloni, usó casos para distinguir átomos y variables. Luego DECsystem 10 Prolog introdujo la notación entre corchetes reemplazando nil y X.Xs por [] y [X,..Xs] que en versiones posteriores de DECsystem 10 recibió [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 muchas funciones diferentes en ISO Prolog. Ya sirve como

  • end token cuando es seguido por un % o un carácter de diseño como SPACE, NEWLINE, PESTAÑA.

  • punto decimal en un número de coma flotante, como 3.14159

  • char formando tokens gráficos como =..

Así que si ahora estás declarando . como un operador de infix, tienes que tener mucho cuidado. Tanto con lo que escribes como con lo que los sistemas Prolog leerán. Un solo espacio adicional puede cambiar el significado de un término. Considere dos listas de números en ambas notaciones:

[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].

Tenga en cuenta que hay que añadir 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. Así:

[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 corchetes redondos dentro de las listas de puntos.

Hoy en día, solo quedan YAP y XSB que todavía ofrecen infix . por defecto – y lo hacen de manera diferente. Y XSB ni siquiera reconoce la sintaxis de puntos anteriores: necesitas corchetes alrededor de algunos de los números no negativos.

Usted escribió que N.H.L parece ser una manera más conveniente de decir [N|[H|L]]. Hay una simple regla de oro para simplificar tales expresiones en ISO Prolog: Cada vez que vea dentro de una lista los tokens | y [ inmediatamente después uno del otro, puede reemplazarlos por , (y eliminar el ] correspondiente en el lado derecho). Así que ahora puedes escribir: [N,H|L] que no se ve que malo.

Usted puede usa 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]].


Otra observación, ya que estás leyendo el documento de Naish: Mientras tanto, es bien entendido que solo es necesario call/N! E ISO Prolog soporta call/1, call/2 hasta call/8.

 33
Author: false,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-23 12:02:32

Sí, tienes razón, el punto es la lista cons operador de infix. 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 */

Se me desaconsejó. Efectivamente, la sintaxis [A|B] es una evolución de la . operador, introducido para la legibilidad.

OT: ¿qué es ese código?

El código anterior es mi intento de endulzar Prolog con funciones. A saber, introduce a petición, por medio de $, las variables temporales requeridas (por ejemplo) por expresiones aritméticas

fact(N, F) :-
     N > 1 -> F is N * $fact($(N - 1)) ; F is 1.

Each introduce 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...

 10
Author: CapelliC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-05 10:11:07

Esta sintaxis proviene de NU-Prolog. Ver aquí. Probablemente sea el funtor normal de la lista.'/2 redefinido como un operador de infix, sin la necesidad de una lista vacía 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)
 9
Author: twinterer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-16 23:05:44