Utilice operadores aritméticos como constructores de tuplas y pares de contras.
Si necesita pasar una sola estructura que consta de dos o más valores, lo más obvio es usar una lista, por ejemplo [A,B]
. Sin embargo, eso es realmente detallado.
Hay una alternativa Los valores de Prolog pueden almacenar una estructura anidada bastante arbitraria, que no se evalúa. Aquí hay un ejemplo que muestra cómo funciona:
| ?- member(member(A,B),C).
C = [member(A,B)|_] ? ;
C = [_,member(A,B)|_] ? ;
(etc.)
member(A,B)
es solo una tupla con nombre en esta situación, y el exterior member
(que es una llamada de función) lo trata como tal.
Aunque las tuplas con nombre son bastante útiles en la programación de Prolog sin golf, pueden parecer aún más detalladas que el enfoque de lista. Sin embargo, podemos usar caracteres bastante arbitrarios en el nombre del constructor de tuplas (suponiendo que se citan correctamente); en lugar de algo lindo member
o un solo personaje a
, podemos hacer algo como esto:
| ?- A = '-'('/'(1,2), '/'(3,4)).
A = 1/2-3/4
Aquí, nuestros constructores de tuplas son '-'
y '/'
. Y es interesante notar lo que hizo la bonita impresora con ellos; usa notación infija para las tuplas. Esto es realmente breve y analiza de la misma manera que lo haría la operación aritmética comparable. (Esto también explica por qué los usos aritméticos is
no =
; A = 1+2
unificaríaA
con la tupla '+'(1,2)
, por lo que se necesita una sintaxis separada para evaluar realmente la expresión aritmética no evaluada). Debido a que un constructor de tuplas debe llamarse algo , también puede usar un carácter que tenga un término breve sintaxis (y como bonificación, -
y/
son algunas de las opciones más comunes en el código no golfizado también cuando quieren un constructor de tuplas desechable rápido en lugar de algo significativo, de la misma manera que a i
menudo se usa como una variable de bucle, por lo que son completamente razonables para usar en su entrada y salida si por casualidad quieres una tupla allí).
'-'
y '/'
son buenas opciones para los constructores de tuplas porque tienen una buena conducta y una precedencia útil, lo que le permite escribir tuples literales de manera clara. Sin embargo, tenga en cuenta que no necesita preocuparse por la precedencia cuando se producen valores intermedios dentro del programa. Prolog mantiene las tuplas almacenadas como un árbol en lugar de como código fuente, y las impresoras bonitas pueden enviarlo sin ambigüedades:
| ?- A = '-'('-'(1,2), '-'(3,4)).
A = 1-2-(3-4)
Debido a que la sintaxis de tupla es muy breve ( f(A,B)
no es más corta quef(A-B)
), puede reemplazar múltiples argumentos de predicción con tuplas sin costo, lo que significa que si un predicado necesita pasar dos o más de sus argumentos a otro predicado, a menudo puede formarlos en una tupla y simplemente pasar la tupla (aunque esto requerirá cambiar todas las llamadas al predicado, además del predicado mismo, para usar una combinación adecuada de constructores de tuplas y comas).
Otra ventaja de esta sintaxis es si necesita usar listas internamente (en lugar de interoperar con predicados estándar); una lista es básicamente solo un conjunto de celdas anidadas, y una celda cons es solo una tupla con constructor '.'
, como se puede ver aquí:
| ?- Q = '.'('.'(A,B),'.'(C,D)).
Q = [[A|B],C|D]
Si su código usa listas "manualmente", puede tener mucho sentido usar un constructor de tuplas menos voluminoso que '.'
. Una opción común para mí es representar una celda de contras como '/'(Tail,Head)
(porque se trata de lo más legible que puede obtener en la salida de depuración sin desperdiciar caracteres). Tenga en cuenta que probablemente también querrá su propio []
equivalente; usted podría utilizar[]
, pero es dos bytes de longitud, y hay un montón de átomos de un byte (todas las letras minúsculas) que se pueden utilizar en su lugar.
Entonces, por ejemplo, la siguiente lista:
[1,2,3]
podría convertirse en una representación manual en el mismo número de caracteres como este:
x/3/2/1
mientras obtiene la ventaja de que [H|T]
las coincidencias de patrones de estilo ahora se pueden escribir de manera más concisa como T/H
, y una prueba contra la lista vacía, en x
lugar de hacerlo por más tiempo []
. (Por supuesto, esto viene con el inconveniente obvio que member
, append
, etc, no funcionará en esta representación.)
prolog
etiqueta es un poco inútil. A menos que tengamos un desafío Interpretar Prólogo, no lo necesitamos.