You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. read_line_to_string/2是SWI专属,GNU Prolog无此谓词,需用read_line_to_codes/2替代后转换类型
  2. sub_string/5替换为GNU支持的sub_atom/5
  3. debug/3是SWI调试工具,GNU无此谓词,需移除或替换为自定义输出
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:37:01