Kenneth Wilhelmsson 1 Logikprogrammering 10 P Onsdag 20 november 2002
Kenneth Wilhelmsson 2 Logikprogrammering 10 P: 20 november 2002 Idag: Filer, strömmar m m
Kenneth Wilhelmsson 3 Repetition Moduler + något nytt En av tenta-uppgifterna Och filhantering fram till dagens egentliga ämne
Kenneth Wilhelmsson 4 Moduler i SICStus Prolog När man använder moduler i Prolog innebär det att predikat som man vill använda kan hämtas från andra filer. Förmodligen är några av Prologs tilläggspredikat bekanta. T ex de som finns i resursmodulen lists.pl m fl.
Kenneth Wilhelmsson 5
6 Hur göra modul? Genom att först i sin prolog-fil (t ex min_fil.pl) skriva följande, definierar man en modul innehållande en delmängd av (alt: samtliga) ingående predikat. :- module(min_fil, [pred1/4, pred5/2, pred2/2]). [programkod…] (Predikaten som finns i listan finns med längre ner i filen)
Kenneth Wilhelmsson 7 Anrop från en modul till en annan :- module(min_fil, [pred1/4, pred5/2, pred2/2]). [programkod…] :- module(andra_filen,[bepa/7]). use_module(min_fil, [pred1/4, pred2/2]). … - Notera att hela modulen ej importeras här.
Kenneth Wilhelmsson 8 Placering av module och use_module module-deklarationen (om sådan finns) skall placeras allra först i filen. Modulnamnet är detsamma som prologfilnamnet, dock utan ”.pl”. use_module-deklarationerna (om sådan finns) skall komma härnäst. Dessa beskriver alltså vilka predikat som importeras till denna modul.
Kenneth Wilhelmsson 9 Om vi inte nämner att vi vill importera ett visst predikat till en modul… Om vi anropar somliga predikat från en fil mha use_module, men inte alla – så behöver inte nya definitioner av den importerade filens samtliga predikat innebära några som helst bekymmer.
Kenneth Wilhelmsson 10 Tentauppgift 3a
Kenneth Wilhelmsson 11 Vad kommer att hända när u1.pl laddas in?
Kenneth Wilhelmsson 12 Svar: Vi får NAME CLASH tre gånger I SICSTUS Prolog betyder det att vi får välja om vi vill byta definition av de drabbade predikaten.
Kenneth Wilhelmsson 13 ”Stor fördel” När vi skriver :-use_module kan vi naturligtvis avstå från att hämta samtliga predikat från en modul. Om vi inte uttryckligen hämtar ett predikat kan vi definiera detta på annat vis i filen utan att råka ut för name clash.
Kenneth Wilhelmsson 14 Ett annat sätt att anropa ett predikat från godtycklig fil kan vara att använda sig av ’:’. Denna funktionalitet finns i första hand för felsökningssyften. Exempel:
Kenneth Wilhelmsson 15
Kenneth Wilhelmsson 16 Disjunktioner i Prolog Hur uttrycker vi disjunktion (eller) i Prolog? kan_prolog(Person):- datalingvist(Person). kan_prolog(Person):- kognitionsvetare(Person). kan_prolog(Person):- gått_prologkurs(Person). Fråga: använder ovanstående definition en inklusiv eller exklusiv definition av eller om vi säger att predikaten motsvarar ”de verkliga betydelserna?” (OR eller XOR?)
Kenneth Wilhelmsson 17 Ett annat sätt att uttrycka disjunktion som kan spara plats: kan_prolog(Person):- (datalingvist(Person) ; kognitionsvetare(Person) ; gått_prologkurs(Person)). (jfr med ”|”-notation i PSG”) Predikatet är ekvivalent med det föregående. (Kompilatorn genererar samma optimaliserade kod för båda varianterna av skrivsätt.)
Kenneth Wilhelmsson 18 Tentauppgift 3a
Kenneth Wilhelmsson 19 Några Prolog-tips (direkt från SICStus-manualen) -Skriv inte predikat om de redan finns bland de fördefinierade. -Inled rekursiva regler med basfall. -Skriv input-argumenten före output-argumenten i regelhuvuden. -Var gärna sparsam med användningen av cut. -När disjunktion skrivs mha semikolon – avsluta ej raden med semikolonet. Och helst inom parenteser.
Kenneth Wilhelmsson 20 Summa-exemplet (summa.pl) % summa(Summa, Tal1, Tal2) % Summa är summan av Tal1 och Tal2, Alla tal anges med % "successor"-notationen för naturliga tal. summa(Tal, 0, Tal). summa(s(Summa), s(Tal1), Tal2) :- summa(Summa, Tal1, Tal2).
Kenneth Wilhelmsson 21 ”Trace är egentligen ett specialfall av spy” (Man tar bort trace genom att skriva notrace ) Spy: spec - Skriv t ex spy member/2. -Spy: [predikat] betyder att man sätter en spy point på ett predikat och får se hur det anropas. Nospy:spec och nospyall tar bort. -”Trace är ett spy” - ”med alla flaggor påslagna” - ”Trace” ger ”exhaustive tracing”
Kenneth Wilhelmsson 22 Ej repetition: Alla predikat: Det går naturligtvis att läsa in samtliga predikat från en modul där de gjorts tillgängliga. Skriv enbart modulnamnet i :-use_module(filnamn). För att göra predikat tillgängliga från modulen mha module() krävs dock att att alla predikat anges. Minns list.pl.
Kenneth Wilhelmsson 23 See/1 för att öppna en fil: see/1 förändrar indataströmmen fullständigt - från tangentbordet till en angiven fil (argumentet) härefter: get_line/1
Kenneth Wilhelmsson 24 Motsvarigheten till see/1 heter tell/1 för att skriva till filer Observera att det gamla textinnehållet raderas och ersätts av vad som anges när tell används. tell(’viktig_fil.txt’). write(’adjö’), nl. told.
Kenneth Wilhelmsson 25 Dagens ämne: En nackdel med tell är att detta predikat – inte möjliggör konkatenering till en fil! tell/1 förstör den gamla filen och ersätter innehållet med något nytt. (Den gamla filen förstörs alltså i det fall den existerar.)
Kenneth Wilhelmsson 26 Tell En annan nackdel med detta predikat är att man kanske vill skriva till två filer samtidigt. Eller kanske till en fil och samtidigt till skärmen. See är inte bättre i detta avseende – hur skulle man kunna läsa från två olika filer samtidigt. (Man behöver ju öppna och stänga hela tiden.)
Kenneth Wilhelmsson 27 Vad som krävs: strömmar och predikat för dessa Mha av predikatet open/3 öppnar man en ström för en viss fil. En ström är en identifierare för en öppnad fil.
Kenneth Wilhelmsson 28 Open/3 open/3 har tre olika användningssätt – read, write och append.
Kenneth Wilhelmsson 29 Öppna och skriva open(hejsan, write, Ström).
Kenneth Wilhelmsson 30 Öppna och skriva på ett mer utförligt sätt Det finns varianter av write, nl, read och get_char för användning i detta sammanhang: öppna_och_skriv:- open(hej,write, min_fil), nl(min_fil), write(min_fil, hå), nl(min_fil), close(min_fil).
Kenneth Wilhelmsson 31 KOPIERA EN FIL TILL EN ANNAN kopiera(Infil,Utfil):- open(Infil, read, Inström), open(Utfil,write, Utström), kopiera-strömmar(Inström,Utström), close(Inström), close(Utström). kopiera_strömmar(Inström, Utström) :- get_char(Inström, X), ( X=end_of_file -> true ; put_char(Utström, X), kopiera_strömmar(Inström, Utström) ).
Kenneth Wilhelmsson 32 Om exemplet Föregående exempel går lika bra att genomföra mha tell/told och see/seen
Kenneth Wilhelmsson 33 Standardströmmarna Det finns tre standardströmmar: En för inmatning, en för utmatning och en för felmeddelanden.
Kenneth Wilhelmsson 34 Standardströmmar Dessa är user_input, user_output och user_error ?- write(user_output, krater). krater ?- read(user_input,X). |: guldälg X = guldälg
Kenneth Wilhelmsson 35 Uppgift: Skriv ett predikat, vänd_lista/2 vars andra argument är den omvända varianten av listan som finns i första argumentet.
Kenneth Wilhelmsson 36 Lösningsförslag Naïve reverse reverse([],[]). reverse([X|Xs], Zs):- reverse(Xs,Ys), append(Ys,[X], Zs).
Kenneth Wilhelmsson 37 Ackumulerad reverse reverse(Xs,Ys):-reverse(Xs,[],Ys). reverse([X|Xs],Acc,Ys):- reverse(Xs, [X|Acc], Ys). reverse([],Ys,Ys).
Kenneth Wilhelmsson 38 Tack för idag