La (-)/2
per rappresentare differenza liste è una convenzione piuttosto rara. Nei libri più vecchi veniva utilizzato anche un altro operatore (\)/2
.
Molti preferiscono utilizzare due argomenti separati invece. Ci sono diversi vantaggi rispetto all'utilizzo di un operatore:
Il predicato non può accidentalmente essere utilizzato con una variabile istanziato per l'argomento. Pensa di chiamare q(A, X)
al posto di q(A, X-[])
.
L'esecuzione è anche un po 'più efficiente quando si utilizzano due argomenti. Molti sistemi, come SWI, devono creare dinamicamente ciascuna struttura (-)/2
.
Tuttavia, c'è anche un altro modo di utilizzare gli elenchi di differenza, che è spesso meno soggetto a errori: Si potrebbe utilizzare una dcg per questo scopo.
In realtà, ci sono due errori nel programma, uno dei quali è causato dal modo in cui viene gestito l'elenco delle differenze. L'altro errore è che il programma non gestisce la fine del file. Sarebbe meglio usare end_of_file
al posto di end
. Ma questa è una cosa superficiale che ti saresti trovato prima o poi.
L'altro, più sottile errore è dovuto all'interazione tra liste di differenza e il taglio. Non sono un grande fan dei tagli, ma esaminiamo questa regola. Un taglio taglia dopo che tutto al suo lato sinistro è stato eseguito.
q(end_of_file,X-X) :- !.
Il primo argomento è l'atomo end_of_file
. Dato che stiamo usando q/2
solo con il risultato di read/1
come primo argomento, questo può essere solo un confronto. Quindi siamo alla fine del file (o stream). Quindi, tuttavia, ci sono altre cose che devono essere mantenute. E solo se anche questi riescono, verrà eseguito il taglio: Il secondo argomento deve essere un (-)/2
(ok, in tutti i punti c'è un meno al suo posto). E poi: i due argomenti di (-)/2
devono essere gli stessi (deve unificare). Perché? Siamo alla fine del file, ma se quegli argomenti non si uniscono, verrà tentata l'altra regola.
Quando succede questo?Ecco un caso così brutto:
p([X,Y,Z]).
E sufficiente inserire una sola costante, dicono my_constant.
quindi premere Cntrl-d o Cntrl + z. Cosa dovrebbe fare p/1
in questo caso? Idealmente, fallirebbe dopo aver finito l'input. Tuttavia, aspetterà ulteriori input.
Il motivo è l'errata collocazione del taglio. Diciamo che p/1
non è steadfast. Questo è un errore comune nei programmi Prolog. Posso solo raccomandare di ridurre l'uso di tagli e l'adozione di DCG. Con DCGs, questo non può accadere:
p2(X) :- read(A), phrase(q2(A),X).
q2(end_of_file) --> !.
q2(A) --> [A], {read(B)}, q2(B).
Con DCGs, il taglio viene eseguito indipendentemente dal motivo di p/1
.
@ p.s.w.g: Perché hai votato per chiudere questo? – false
''-'' qui non è un predicato, è un" functor "- nome di una struttura composta. Per esempio. in 'f (1,2)', 'f' è un funtore di un termine composto con due argomenti. (se cerchi, cerca "Prolog functor", solo "functor" ti mostrerà una tonnellata di cose non correlate). –
Hai perfettamente ragione - sfortunatamente, non mi permette di rimuovere la bandiera. Ho cancellato il mio commento, comunque. –