Operatori in Prolog
(vedi anche il manuale del Prolog-SWI)
Gli operatori giocano da un punto di vista sintattico il ruolo di normali funtori, un operatore cioè è solo un modo conciso e più leggibile per esprimere particolari funtori. Ad esempio per scrivere 2*3+4*5 senza operatori sarebbe necessario scrivere +(*(2,3),*(4,5)).
In Prolog esistono degli operatori predefiniti (aritmetici, relazionali, logici) ed è possibile definirne di nuovi.
Ogni operatore è caratterizzato da
• nome
• numero di argomenti (uno o due)
• posizione: prefissa, infissa (solo per operatori binari), postfissa
• precedenza (è indicata con un numero, compreso in un intervallo dipendente dalla particolare implementazione, più basso è il numero, più alta è la precedenza nell’ordine di applicazione in assenza di parentesi, in modo più stretto l’operatore lega i suoi argomenti. Ad esempio * ha precedenza 400, + ha precedenza 500, 400 è minore di 500, quindi * lega più stretto di +, * ha precedenza più alta di +, viene applicato prima il * perché ha precedenza più alta)
• associatività (serve per disambiguare espressioni con un solo operatore o con operatori tutti con la stessa precedenza. Un operatore può essere non associativo oppure associativo a destra o a sinistra. Gli operatori aritmetici, per esempio, sono associativi a sinistra).
Per definire un nuovo operatore si usa il predicato predefinito op(PR, TIPO, NOME)
che definisce un operatore con nome NOME, priorità PR e tipo TIPO.
NOME è il nome che si intende dare all’operatore o una lista di nomi (così si definiscono più operatori con stessa priorità e tipo).
PR è la priorità
TIPO specifica il numero degli argomenti e l’associatività. I tipi possibili sono quelli in grassetto
• f indica la posizione dell’operatore
• fx fy si usano per indicare operatori unari prefissi
• xf yf si usano per indicare operatori unari postfissi
• xfx yfx xfy si usano per operatori binari
• x indica un argomento che è o un atomo
o un’espressione tra parentesi (la quale ha precedenza 0)
o un’espressione il cui operatore principale ha priorità strettamente minore di quella dell’operatore che si sta definendo
• y indica un argomento che è o un atomo
o un’espressione tra parentesi (la quale ha precedenza 0)
o un’espressione il cui operatore principale ha priorità minore o uguale di quella dell’operatore che si sta definendo
• yfx indica un operatore associativo a sinistra (es. A+B+C è (A+B)+C )
• xfy indica un operatore associativo a destra (es. A; B; C è A; (B;C))
• xfx indica un operatore non associativo.
Per capire la differenza tra x e y vediamo l’esempio seguente: definisco l’operatore >> con tipo fx
?- op(500,fx,>>).
Se scrivo
X = >> >> p.
Ottengo
Syntax error: Operator priority clash
Perché a destra dell’operatore dovrei averne uno con precedenza minore
Se lo definisco
?- op(500,fy,>>).
e chiedo
X= >> >> p, X= >> Y.
ottengo invece
X = >> >>p, Y = >>p
Il tipo xfy dichiara un operatore associativo a destra. Ad esempio, definiamo
?- op(500,xfy,>>).
La query
X >> Y = a >> b >> c.
ottiene come risposta
X = a, Y = b>>c
Il tipo yfx invece dichiara un operatore associativo a sinistra:
?- op(500,yfx,>>).
e la query
X >> Y = a >> b >> c.
ottiene la risposta
X = a>>b Y = c
Il tipo xfx, ovvero non associativo, darebbe errore alla query vista sopra:
?- op(500,xfx,>>).
X >> Y = a >> b >> c.
ERROR: Syntax error: Operator priority clash ERROR: X >> Y = a >>
ERROR: ** here **
ERROR: b >> c . Per comprendere le priorita', vediamo i seguenti esempi:
?- op(500,xfx,>>).
?- op(400,xfx,**).
?- X ** Y = a ** b >> c.
No
?- X >> Y = a ** b >> c.
X = a**b Y = c
** ha precedenza minore quindi lega piu' stretto: è come se l’espressione a ** b >> c fosse (a ** b) >> c quindi non unifica con X ** Y, mentre unifica con X >> Y