Prolog på villspor: Fire vanlige tabber i logisk programmering

Prolog på villspor: Fire vanlige tabber i logisk programmering

Mai 18, 2026 prolog logic-programming code-quality declarative-programming software-engineering constraint-logic-programming best-practices

Fire år med logikkprogrammering som kan gå galt

Prolog har en sær tiltrekning. Mens de fleste utviklere velger imperative språk og objektorientering, holder Prolog-folk fast ved en helt annen måte å tenke på. Det føles både elegant og annerledes – helt til koden plutselig ikke lenger virker som den skal.

Noen få grunnprinsipper skiller god Prolog fra kode som skjult faller fra hverandre i produksjon. Bryter du dem, risikerer du resultater som enten er feil, mangler løsninger eller blir umulige å teste. Her er de fire klassiske fellene.

1. Cut som dreper løsninger

Når en predikat fungerer fint med konkrete verdier, men svikter når noen stiller et mer generelt spørsmål, ligger ofte en cut (!) eller en if-then-else (->) bak. De samme mekanismene som gjør koden «raskere» eller «enklere» for deg, gjør den også mindre generell.

factorial(0, 1) :- !.
factorial(N, F) :-
    N > 0,
    N1 is N - 1,
    factorial(N1, F1),
    F is N * F1.

Når du spør ?- factorial(N, F). får du bare én rad. Alt annet forsvinner, fordi cut-en blokkerer backtracking. Bedre er det å bruke dif/2 og høyereordens predikater. Da holder koden seg ren og testbar.

2. Mutering av databasen

Når mange begynner å bruke assertz/1 og retract/1, føler de seg som en slags magiker. De kan endre kunnskapsbasen mens programmet kjører. Men hver gang du muterer globalt, bygger du opp usynlige avhengigheter.

Tilstand som ikke flyter gjennom argumenter, men ligger skjult i databasen, gjør både testing og feilsøking til et mareritt. Hvert testløp kan etterlate spor som ødelegger neste kjøring. Løsningen er enkel: send tilstanden gjennom argumenter eller bruk kontekstnotasjon.

3. Blanding av logikk og utskrift

solve_and_print :-
    solution(S),
    format("The solution is: ~q~n", [S]).

En slik blanding gjør det umulig å teste eller gjenbruke predikatet. Du får kun utskrift på skjermen, ikke et Prolog-term du kan jobbe videre med. Separat logikk og presentasjon: la predikatet beskrive løsningen, mens øverste nivå tar seg av formatet.

4. Gamle aritmetikk-predikater

Mange holder fortsatt fast ved (is)/2, (=:=)/2 og (>)/2 fordi «det har alltid fungert». Men de siste tjue årene har Constraint Logic Programming over Finite Domains (CLP(FD)) gjort det mulig å skrive koden som en ren spesifikasjon.

Low-level-konstruktene blander deklarativ intensjon med operasjonelle detaljer – en belastning spesielt for nybegynnere. Med CLP(FD) blir intensjonen tydelig og koden lettere å lese.

Når alt går galt på én gang

horror_factorial(0, 1) :- !.
horror_factorial(N, F) :-
    N > 0,
    N1 is N - 1,
    horror_factorial(N1, F1),
    F is N * F1.

Denne versjonen bryter flere prinsipper samtidig: cut ødelegger backtracking, lavnivå-aritmetikk krever korrekt instantiert input, og koden fungerer bare som funksjon – ikke som relasjon. Når du spør etter alle gyldige kombinasjoner av N og F, får du bare én løsning.

Slik skriver du bedre Prolog

  • Bruk deklarative mønstre og høynivå-verktøy fremfor cut og type-sjekk.
  • Hold tilstanden synlig – send den gjennom argumenter.
  • Skill logikk fra presentasjon.
  • Bytt til CLP(FD) og moderne abstraksjoner.

Når Prolog-koden din svarer på det mest generelle spørsmålet og leses som en ren spesifikasjon, får du den sanne kraften av logikkprogrammering. Da blir både utvikling og vedlikehold langt mer behagelig.

Read in other languages:

RU BG EL CS UZ TR SV FI RO PT PL NL HU IT FR ES DE DA ZH-HANS EN