Usa operatori aritmetici come costruttori di tuple e coppie di contro
Se è necessario passare una singola struttura composta da due o più valori, la cosa più ovvia da utilizzare è un elenco, ad es [A,B]. È davvero prolisso, però.
C'è un'alternativa. I valori di Prolog possono memorizzare una struttura annidata praticamente arbitraria, che non viene valutata. Ecco un esempio che mostra come funziona:
| ?- member(member(A,B),C).
C = [member(A,B)|_] ? ;
C = [_,member(A,B)|_] ? ;
(etc.)
member(A,B)è solo una tupla nominata in questa situazione e l'esterno member(che è una chiamata di funzione) la sta trattando come tale.
Sebbene le tuple nominate siano abbastanza utili nella programmazione Prolog senza golf, potrebbero sembrare ancora più dettagliate dell'approccio dell'elenco. Tuttavia, possiamo usare praticamente dei caratteri arbitrari nel nome del costruttore della tupla (supponendo che siano correttamente citati); invece di qualcosa di carino membero di un singolo personaggio a, possiamo fare qualcosa del genere:
| ?- A = '-'('/'(1,2), '/'(3,4)).
A = 1/2-3/4
Qui sono i nostri costruttori di tuple '-' e '/'. Ed è interessante notare cosa ha fatto la bella tipografa con loro; sta usando la notazione infissa per le tuple. Questo è davvero conciso e analizza allo stesso modo dell'operazione aritmetica comparabile. (Questo spiega anche perché l'aritmetica isnon lo usa =; A = 1+2si unirebbe Acon la tupla '+'(1,2) , quindi è necessaria una sintassi separata per valutare effettivamente l'espressione aritmetica non valutata.) Perché un costruttore di tuple deve essere chiamato qualcosa , puoi anche usare un carattere che ha una terse sintassi (e come bonus, e sono alcune delle scelte più comuni nel codice non golfato anche quando vogliono un costruttore di tuple usa e getta piuttosto che qualcosa di significativo, più o meno allo stesso modo-/i viene spesso utilizzato come variabile loop, quindi sono del tutto ragionevoli da utilizzare nel tuo input e output se ti capita di volere una tupla per qualche motivo).
'-'e '/'sono buone scelte per i costruttori di tuple perché hanno una precedenza ben educata e utile, che ti consente di scrivere letteralmente tuple. Tuttavia, si noti che non è necessario preoccuparsi della precedenza quando vengono prodotti valori intermedi all'interno del programma. Prolog mantiene le tuple archiviate come albero anziché come codice sorgente e pretty-printers può produrlo in modo inequivocabile:
| ?- A = '-'('-'(1,2), '-'(3,4)).
A = 1-2-(3-4)
Perché la sintassi della tupla è così concisa ( f(A,B)non è più breve dif(A-B) ), è possibile sostituire gratuitamente più argomenti prediccati con tuple, il che significa che se un predicato deve passare due o più dei suoi argomenti a un altro predicato, è spesso possibile formarli in una tupla e basta passare la tupla (anche se ciò richiederà la modifica di tutte le chiamate al predicato, oltre al predicato stesso, per utilizzare un appropriato mix di costruttori e virgole di tuple).
Un altro vantaggio di questa sintassi è se è necessario utilizzare gli elenchi internamente (anziché interagire con i predicati standard); un elenco è fondamentalmente solo un insieme di celle contro nidificate e una cella contro è solo una tupla con costruttore '.', come si può vedere qui:
| ?- Q = '.'('.'(A,B),'.'(C,D)).
Q = [[A|B],C|D]
Se il tuo codice utilizza gli elenchi "manualmente", può avere molto senso usare un costruttore di tuple meno ingombrante di '.' . Una scelta comune per me è quella di rappresentare una cella di contro come '/'(Tail,Head)(perché è il più leggibile che puoi ottenere nell'output di debug senza sprecare caratteri). Nota che probabilmente vorrai anche il tuo []equivalente; si potrebbe usare[] , ma si tratta di due byte lungo, e ci sono un sacco di atomi di un byte (tutte le lettere minuscole) che è possibile utilizzare invece.
Ad esempio, il seguente elenco:
[1,2,3]
potrebbe essere convertito in una rappresentazione manuale nello stesso numero di caratteri come questo:
x/3/2/1
pur ottenendo il vantaggio che le [H|T]corrispondenze di modelli in stile ora possono essere scritte in modo più rapido T/He un test sull'elenco vuoto come solo xpiuttosto che più lungo []. (Naturalmente, questo viene fornito con lo svantaggio ovvio che member, appendecc, non funziona su questa rappresentazione.)
prologtag è un po 'inutile. A meno che non abbiamo una sfida Interpret Prolog, non ne abbiamo bisogno.