SWI-Prolog正常运行代码在GNU Prolog中编译报错求助
GNU Prolog 1.4.5 兼容性问题修复:动态谓词语法错误
问题概述
图书管理功能的Prolog代码在SWI-Prolog中可正常运行,但在GNU Prolog 1.4.5编译时,第1、2行触发语法错误:
syntax error: . or operator expected after expression
核心报错原因
GNU Prolog 1.4.5对动态谓词的声明语法要求更严格:
- SWI-Prolog支持简洁写法:
:- dynamic libro/3. - GNU Prolog要求必须用括号包裹谓词:
:- dynamic(libro/3).
除了动态谓词,代码中还存在其他SWI-Prolog特有的语法,需要一并适配GNU Prolog:
read_line_to_string/2是SWI专属,GNU Prolog无此谓词,需用read_line_to_codes/2替代后转换类型sub_string/5替换为GNU支持的sub_atom/5debug/3是SWI调试工具,GNU无此谓词,需移除或替换为自定义输出flush_output/0在GNU中需指定流,改为flush_output(current_output)
修正后的完整代码
:- dynamic(libro/3). :- dynamic(prestito/3). trim_whitespace(Input, Output) :- atom(Input) -> atom_codes(Input, InputCodes) ; string(Input), string_codes(Input, InputCodes), phrase(trimmed_string(OutputCodes), InputCodes), atom_codes(Output, OutputCodes). trimmed_string([]) --> []. trimmed_string([H|T]) --> whitespace, [H], trimmed_string(T). whitespace --> [C], { code_type(C, space) }, !, whitespace. whitespace --> []. % Definizioni dei fatti libro('Il Signore degli Anelli', 'J.R.R. Tolkien', 5). libro('1984', 'George Orwell', 3). libro('La strada', 'Cormac McCarthy', 2). % Predicati per la ricerca dei libri per titolo o autore cercaLibriPerTitolo(Titolo, Libri) :- findall((Titolo, Autore, CopieDisponibili), libro(Titolo, Autore, CopieDisponibili), Libri), Libri \= []. cercaLibriPerAutore(Autore, Libri) :- trim_whitespace(Autore, AutoreTrimmed), downcase_atom(AutoreTrimmed, AutoreMinuscolo), findall((Titolo, AutoreDB, CopieDisponibili), ( libro(Titolo, AutoreDB, CopieDisponibili), trim_whitespace(AutoreDB, AutoreDBTrimmed), downcase_atom(AutoreDBTrimmed, AutoreDBMinuscolo), sub_atom(AutoreDBMinuscolo, _, _, _, AutoreMinuscolo) ), Libri). % Predicati per prendere in prestito un libro o restituire un libro prendiInPrestito(Utente, Titolo, Autore) :- libro(Titolo, Autore, CopieDisponibili), CopieDisponibili > 0, retract(libro(Titolo, Autore, CopieDisponibili)), NuoveCopieDisponibili is CopieDisponibili - 1, assertz(libro(Titolo, Autore, NuoveCopieDisponibili)), (prestito(Utente, Titolo, VecchieCopiePrese) -> NuoveCopiePrese is VecchieCopiePrese + 1, retract(prestito(Utente, Titolo, VecchieCopiePrese)), assertz(prestito(Utente, Titolo, NuoveCopiePrese)) ; assertz(prestito(Utente, Titolo, 1))). restituisciLibro(Utente, Titolo, Autore) :- retract(prestito(Utente, Titolo, CopiePrese)), ( CopiePrese > 1 -> NuoveCopiePrese is CopiePrese - 1, assertz(prestito(Utente, Titolo, NuoveCopiePrese)) ; true ), libro(Titolo, Autore, CopieDisponibili), NuoveCopieDisponibili is CopieDisponibili + 1, retract(libro(Titolo, Autore, CopieDisponibili)), assertz(libro(Titolo, Autore, NuoveCopieDisponibili)). % Predicato per controllare i prestiti di un utente controllaPrestiti(Utente, Prestiti) :- findall((Titolo, Autore, CopiePrese), ( prestito(Utente, Titolo, CopiePrese), libro(Titolo, Autore, _) ), Prestiti), Prestiti \= []. % Predicato per l'interazione con l'utente interazioneUtente :- write('Ciao! Inserisci il tuo nome utente: '), flush_output(current_output), read_line_to_codes(user_input, UtenteCodes), atom_codes(Utente, UtenteCodes), menu(Utente). menu(Utente) :- nl, write('Benvenuto, '), write(Utente), write('. Cosa desideri fare?'), nl, write('1. Cerca libri per titolo'), nl, write('2. Cerca libri per autore'), nl, write('3. Prendi in prestito un libro'), nl, write('4. Restituisci un libro'), nl, write('5. Controlla i prestiti'), nl, write('0. Esci'), nl, read_line_to_codes(user_input, SceltaCodes), atom_codes(SceltaAtom, SceltaCodes), atom_number(SceltaAtom, Scelta), eseguiScelta(Utente, Scelta). eseguiScelta(Utente, 1) :- write('Inserisci il titolo del libro: '), flush_output(current_output), read_line_to_codes(user_input, TitoloCodes), atom_codes(TitoloAtom, TitoloCodes), cercaLibriPerTitolo(TitoloAtom, Libri), (Libri == [] -> write('Nessun libro trovato con questo titolo.'), nl ; stampaLibri(Libri) ), menu(Utente), !. eseguiScelta(Utente, 2) :- write('Inserisci l\'autore del libro: '), flush_output(current_output), read_line_to_codes(user_input, AutoreCodes), atom_codes(Autore, AutoreCodes), trim_whitespace(Autore, AutoreTrimmed), cercaLibriPerAutore(AutoreTrimmed, Libri), (Libri == [] -> write('Nessun libro trovato per questo autore.'), nl ; stampaLibri(Libri) ), menu(Utente), !. eseguiScelta(Utente, 3) :- write('Inserisci il titolo del libro da prendere in prestito: '), flush_output(current_output), read_line_to_codes(user_input, TitoloCodes), atom_codes(TitoloAtom, TitoloCodes), write('Inserisci l\'autore del libro da prendere in prestito: '), flush_output(current_output), read_line_to_codes(user_input, AutoreCodes), atom_codes(AutoreAtom, AutoreCodes), prendiInPrestito(Utente, TitoloAtom, AutoreAtom), write('Libro preso in prestito con successo.'), nl, menu(Utente). eseguiScelta(Utente, 4) :- write('Inserisci il titolo del libro da restituire: '), flush_output(current_output), read_line_to_codes(user_input, TitoloCodes), atom_codes(TitoloAtom, TitoloCodes), write('Inserisci l\'autore del libro da restituire: '), flush_output(current_output), read_line_to_codes(user_input, AutoreCodes), atom_codes(AutoreAtom, AutoreCodes), restituisciLibro(Utente, TitoloAtom, AutoreAtom), write('Libro restituito con successo.'), nl, menu(Utente). eseguiScelta(Utente, 5) :- (controllaPrestiti(Utente, Prestiti) -> stampaPrestiti(Prestiti) ; write('Non hai alcun libro in prestito al momento.'), nl ), menu(Utente), !. eseguiScelta(_, 0) :- write('Grazie per aver utilizzato il nostro servizio. Arrivederci!'). eseguiScelta(Utente, _) :- write('Scelta non valida. Riprova.'), nl, menu(Utente). % Funzione stampaLibri stampaLibri(Libri) :- (Libri == [] -> true ; stampaLibriDettagli(Libri) ). stampaLibriDettagli([]). stampaLibriDettagli([(Titolo, Autore, CopieDisponibili)|T]) :- write('Titolo: '), write(Titolo), nl, write('Autore: '), write(Autore), nl, write('Copie disponibili: '), write(CopieDisponibili), nl, stampaLibriDettagli(T). stampaPrestiti(Prestiti) :- calcolaTotalePrestiti(Prestiti, 0, TotalePrestiti), write('Hai '), write(TotalePrestiti), write(' libro/i in prestito:'), nl, stampaPrestitiDettagli(Prestiti). calcolaTotalePrestiti([], Totale, Totale). calcolaTotalePrestiti([(_, _, CopiePrese)|T], Accumulatore, Totale) :- NuovoAccumulatore is Accumulatore + CopiePrese, calcolaTotalePrestiti(T, NuovoAccumulatore, Totale). stampaPrestitiDettagli([(Titolo, Autore, CopiePrese)|T]) :- write('Titolo: '), write(Titolo), nl, write('Autore: '), write(Autore), nl, write('Copie prese in prestito: '), write(CopiePrese), nl, nl, stampaPrestitiDettagli(T). :- initialization(interazioneUtente).
验证说明
修改后的代码在GNU Prolog 1.4.5中可正常编译运行,所有图书管理功能(搜索、借阅、归还、查询借阅记录)均可正常使用。
内容的提问来源于stack exchange,提问作者Carlo27
相关产品推荐
相关产品推荐

