2016-02-25 10 views
6

stavo lavorando su un problema Prolog che consiste nel contare il numero di elementi di una lista:Contare il numero di elementi di una lista: come funziona affettazione

count([], 0). 
count([H|T], N) :- 
    count(T, X), 
    N is X+1, 
    N > 0. 

posso capire il motivo per cui è scritto così, ma io non capisco perché non possiamo sostituire N è X + 1 di X è N-1?

Grazie mille!

+0

Nit minore: affettività significa piuttosto assegnazione. – false

risposta

5

La tua domanda è molto legittima, +1.

La ragione di questa scelta apparentemente arbitraria è che (is)/2 è un basso livello predicato comparativamente e funziona solo in casi molto specifici che possono essere comprese solo procedurale, non dichiarativo. Pertanto, (is)/2 è estremamente difficile da comprendere per i principianti e dovrebbe essere evitato perché distrugge molte proprietà relazionali di cui vogliamo godere quando utilizziamo Prolog.

La soluzione dichiarativa utilizza i limiti , dove è possibile fare esattamente ciò che si dice. Per le relazioni su interi, è sufficiente sostituire (is)/2 per (#=)/2 per godere delle proprietà relazionali che si prevede intuitivamente.

Ad esempio, utilizzando GNU   Prolog:

 
count([], 0). 
count([_|Ls], N) :- 
     count(Ls, X), 
     X #= N - 1, 
     N #> 0. 

In altri sistemi come SICStus Prolog e SWI, è attualmente ancora bisogno di utilizzare library(clpfd) per questo. Inoltre, mi raccomando un nome più dichiarativo per questa relazione, rendendo chiaro che l'argomento denota ciò:

 
:- use_module(library(clpfd)). 

list_length([], 0). 
list_length([_|Ls], N) :- 
     list_length(Ls, X), 
     X #= N - 1, 
     N #> 0. 

query di esempio:

 
?- list_length([_,_,_], N). 
N = 3. 

?- list_length(Ls, 2). 
Ls = [_G602, _G605] . 

lascio migliorare le proprietà di terminazione di questo predicato come un facile esercizio.

+1

Grazie per il tuo tappetino per le risposte dettagliato! All'inizio della tua risposta, hai detto che (è)/2 funziona in casi molto specifici. Sai dove posso trovare ulteriori informazioni su questo? Nel sito web SWI-Prolog, si dice che dovrebbe essere usato con un operando di sinistra non associato, ma non è molto chiaro per me (nelle mie lezioni, dice "Il termine di destra dovrebbe essere completamente istanziato al momento della chiamata. "). – azekirel555

+1

Non c'è da stupirsi che questo non sia molto chiaro per te: specialmente come principiante, non hai quasi nessuna possibilità di capire come '(is)/2' deve essere usato. Per riferimento futuro, ti faccio solo sapere che il suo lato destro deve essere completamente istanziato, e il suo lato sinistro dovrebbe essere una variabile * al momento in cui l'obiettivo è chiamato * (ugh!). Ma perché preoccuparsi di questa logica * hacking * invece di logic * programming *? Usa '(# =)/2' e' (#>)/2' dappertutto, e goditi la natura relazionale di questi predicati, che sono utilizzabili in ** tutte ** le direzioni. Ho aggiunto ulteriori spiegazioni su questo alla mia risposta. – mat

+0

La tua ultima osservazione potrebbe essere un po 'troppo indiretta ... – false

Problemi correlati