Varsinainen aihe on Visual Prolog. Visual Prologista kerrotaan sovelluskehitysvälineenä yleisesti ja käydään läpi sen integroitu ohjelmointiympäristö. Keskeistä luvussa on yksinkertaisen esimerkkiohjelman laatimisen esittely.
Valitettavasti Prolog suunniteltiin alunperin tulkkipohjaiseksi kieleksi. Prolog-tulkeissa kiteytyy tulkkien kiroukset eli hitaus ja resurssien tehoton käyttö. Tätä kuvaa hyvin toteamus "Traditional Prolog is a memory hog and to produce real-life applications, one should have fairly unreal (read: expensive, large) computers."
Program Development Center (PDC) oli vielä 80-luvun lopulla osa Borlandin ohjelmistotaloa. Tällöin Borlandilla oli markkinoilla Turbo Prolog -niminen kääntäjä. Ensimmäinen PDC:n emoyhtiöstä irtautumisensa jälkeen lanseeraama kääntäjä oli mielikuvituksellisesti PDC-Prolog. Se oli PC-ympäristöön tarkoitettu Prolog kääntäjä. Tällä hetkellä PDC:n päätuote on Visual Prolog.
Visual Prolog on aito Prolog-kääntäjä, jonka koodia voi
verrata minkä tahansa C++-kääntäjän tuottamaan
koodiin. Standardiin Prologiin nähden Visual Prolog
-kääntäjässä on jouduttu tekemään joitakin
kompromisseja. Esimerkiksi Standardi Prolog voi käyttää dataa
koodina. Visual Prologilla voidaan kuitenkin emuloida myös
standardi-Prologia kääntämällä Prolog-tulkki Visual
Prologille.
Visual Prologiin on sisällytetty interaktiivinen
sovelluskehitysympäristö VDE (Visual Development Environment). Sen
avulla on helppo laatia graafisia ohjelmia, jotka on lisäksi mahdollista
siirtää eri ympäristöihin, kuten esimerkiksi MS-DOS,
Windows ja OS/2 käyttöjärjestelmille.
Proseduraalisella kielellä kirjoitetun ohjelman toiminta määräytyy sarjasta peräkkäin suoritettavia operaatioita. Ohjelmoijan on itse jaettava käsiteltävä ongelma palasiin, jotka voidaan ratkaista proseduraalisesti. C/C++ -kieltä käytetään jatkossa esimerkkinä tyypillisestä proseduraalisesta kielestä.
Proseduraalisessa ohjelmassa voidaan erottaa syöttö-, käsittely- ja tulostustoiminnot, jotka sisältävät paljon if- ja for- lauseita. Erilaiset silmukat voidaan aina ajatella sofistikoidummaksi muodoksi goto-käskystä. Silmukkojen runsaus tekee ohjelmasta vaikean testata ja ylläpitää.
Prolog on ilmeinen edistysaskel proseduraalisista kielistä kohti deklaratiivisuutta. Prolog-ohjelma koostuu säännöistä ja määrittelyistä, joiden puitteissa Prologin päättelykone hakee ratkaisuja. On tärkeää huomata, että se miten ratkaisuun loppujen lopuksi päästään on sisäisen päättelykoneen huoli.
Prologissa toiminta perustuu sisäiseen päättelykoneeseen. Muita läheisesti Prologiin liittyviä käsitteitä ovat mm. epädeterministisyys (moniarvoiset predikaatit), samastus, peräytys- eli hakutoiminto ja rekursio. Näistä lisää seuraavassa luvussa.
Esimerkki 2.1. Prologilla voidaan ohjelmoida myös käyttäen proseduraalista tapaa. Seuraavassa esimerkki for -silmukasta Prologilla:
% for-lauseen määrittely for(X,_,X). for(A,B,I):- B>A, A1=A+1, for(A1,B,I). % esimerkki for-lauseen käytöstä kaksiulotteinen_toisto:- for(1,100,I), for(1,100,J), tee_jotain(I,J), J=100, I=100.
Tähän suppeaan esittelyyn ei ole nähty tarpeelliseksi mahduttaa luetteloa Prologin vakiopredikaateista. Esimerkkiohjelmat on tehty Visual Prologin notaatiolla.
p :- q1, q2, ..., qn Waterloon Prolog
(p q1 q2 ... qn) Micro-Prolog Lisp-notaatio
p if q1 and q2 and ... and qn Micro-Prolog Simple-notaatio
Sisäinen tietokanta on siis maailma, jossa päättelykone toimii. Sisäinen tietokanta muodostuu tosiasioista (faktat) ja säännöistä (predikaatit).
Predikaatti on ohjelman peruskomponentti, joka sisältää kyselyitä. Kun predikaatti on "ratkaistu", muuttuu se faktaksi. Samalla Predikaatilla voi olla useita rinnakkaisia ja vaihtoehtoisia määritelmiä l. lausekkeita. Faktat ovat Prologin tietokannan komponentteja.
Esimerkki 3.1. Faktoja ja predikaatteja:
% kommentti alkaa prosenttimerkillä PREDICATES dad(symbol, symbol) mam(symbol, symbol) son(symbol, symbol) girl(symbol, symbol) man(symbol) CLAUSES dad(Teemu, Eemil). %elämän tosiasia1: Teemu on Eemilin isä. mam(Sirpa, Eemil). %elämän tosiasia2: Sirpa on Eemilin äiti. man(Eemil). son(X,Y):- %sääntö `X on Y:n poika' on tosiasia, jos dad(Y,X), %Y on X:n isä ja man(X). %X on mies. GOAL son(X, Teemu).Esimerkin 3.1. kysely palauttaisi vastaukseksi `Eemil', kuten arvata saattaa.
Anonyymimuuttuja `_' on Prologin erikoisuus. Se on erikoismuuttuja, jolla ilmaistaan, että kohdassa olevan muuttujan arvolla ei ole merkitystä.
Samastus on tapa, jolla päättelykone vertaa ohjelman eri komponentteja toisiinsa. Se tarkoittaa itse asiassa muuttujien ja tietorakenteiden tarkistamista seuraavasti:
DOMAINS nimi = string taso = integer paiva = symbol tunnit = integer minuutit = integer kello = aika(paiva, tunnit,minuutit) luentoaika = alkaa_loppuu(kello, kello) luentoajat = luentoaika* DATABASE -faktat kurssi(nimi, taso, luentoajat) PREDICATES %tässä ohjelmassa ei ole varsinaisia predikaatteja! CLAUSES kurssi("Fortran-kieli", "CL", [ alkaa_loppuu(aika(torstai, 12,00), aika(torstai,14,00)), alkaa_loppuu(aika(perjantai,8,00), aika(perjantai,10,00)) ]). kurssi("Tekoäly", "L", [ alkaa_loppuu(aika(tiistai, 14,00),aika(tiistai,16,00)), alkaa_loppuu(aika(torstai,14,00),aika(torstai,16,00)) ]). GOAL kurssi(_,"L",_).Esimerkin 3.2. kysely palauttaisi kaikki tietokantaan tallennetut laudatur-tasoiset kurssit.
L = [clinton, bush, reagan]. %listanotaatio [Eka|Loput] = L. %muuttujassa `Eka' on clinton ja %lista `Loput' on [bush,reagan]
CLAUSES kertoma(1, 1) :- !. %1! = 1. kertoma(X, KertX) :- %jos X>1, niin sovelletaan tätä määritelmää. Y = X-1, kertoma(Y, kertY), %lasketaan X:n edeltäjän kertoma. KertX = X*KertY. %X! = X:n edeltäjän kertoma * X.Rekursiota käyttäen voidaan esittää algoritmeja, joita ei muuten voitaisi kivuttomasti esittää. Listojen käsittelyssä rekursio on usein lyömätön.
Prolog-ohjelmat ovat epädeterministisiä. Epädeterministisyydellä tarkoitetaan tässä moniarvoisuutta eli Prolog-ohjelma voi palauttaa useitakin vastauksia. Tämä johtuu siitä, että samalla predikaatilla voi olla useita rinnakkaisia määrittelyjä.
Joskus on tarve saada Prolog-ohjelmaan deterministisyyttä. Näin esimerkiksi silloin, kun tarvitaan vain yksi ratkaisu tai kun halutaan tehostaa ohjelman toimintaa.
Katkaisutermillä `!' voidaan ohjelmaan lisätä deterministisyyttä. Katkaisutermi estää muiden ratkaisujen haun. Se nopeuttaa ohjelman suoritusta kahdella tavalla. Ensinnäkin säästytään turhien tai olemattomien ratkaisujen etsimiseltä. Toisaalta katkaisutermin käyttö säästää pinoa, koska deterministisen predikaatin ei tarvitse tallentaa peräytymisreittiään.
Visual Prologissa on mahdollista asettaa epädeterministisyyden varoitus päälle "Compiler Options" -dialogissa. Usein epädeterministisyydestä on haittaa ja se hidastaa sovelluksen toimintaa, mutta joskus se on oleellinen osa sovelluksen toimintaa.
Esimerkki 3.4. Epädeterministinen Prolog-ohjelma palauttaa 2. asteen yhtälön kaikki reaalijuuret.
PREDICATES determinantti(integer, integer, integer) toisen_asteen_yhtälö(integer, integer, integer, integer) ratkaise_yhtälö CLAUSES determinantti(A,B,C,D):- Y = B*B-4*A*C, Y >= 0, D = sqrt(Y). toisen_asteen_yhtälö(A,B,C,X):- %ensimmäinen ratkaisu determinantti(A,B,C,D), X = (-B-D)/(2*A). toisen_asteen_yhtälö(A,B,C,X):- %toinen ratkaisu determinantti(A,B,C,D), X = (-B+D)/(2*A). ratkaise_yhtälö:- write("Anna vakiot A,B,C:"), readreal(A), readreal(B), readreal(C), writef("Yhtälö on %*X*X+% = 0\n",A,B,C), toisen_asteen_yhtälö(A,B,C,X), writef("Juuri = %4.2",X). GOAL ratkaise_yhtälö.Esimerkin 3.3. ohjelma kysyy käyttäjältä 2. asteen yhtälön Ax^2 + Bx + C = 0 vakiotermit A, B, ja C ja palauttaa yhtälön ratkaisut. Ohjelman idea on siinä, että predikaatilla toisen_asteen_yhtälö on kaksi rinnakkaista määrittelyä, yksi molemmille reaalijuurille. Prolog-tulkki kaivaa ratkaisut molempien predikaattimäärittelyjen alta, koska sitä ei ole katkaisumerkeillä estetty.
Prologissa on sisäänrakennettu menetelmä tietokantojen ja tietorakenteiden käsittelyyn. Sen sisäänrakennetun ohjausmekanismin (samastus ja peräytys) ansioista sovelluksesta voidaan karsia tuottavuutta ja ylläpidettävyyttä heikentäviä silmukoita.
Prolog tukee ns. sipuliprotoilua, eli toisin sanoen ohjelman kehittäminen voidaan aloittaa keskeisistä osista ja edetä kerros kerrokselta. Prolog on korkean tason ohjelmointikieli, joten määrittely- ja suunnitteluvaihe ennen varsinaista toteutusta jää melko lyhyeksi. Edellä mainituista seikoista johtuen ohjelman testaus voidaan aloittaa hyvin aikaisessa vaiheessa.
Perinteinen vaihejako Prolog-sovelluksen kehittämiseen on seuraava:
Ohjelman polkujen testaus (whitebox-testaus) sujuu Prologin tulkin avulla. Tosin myös monessa kehittyneessä proseduraalisessa kielessä on varsin kehittyneet debuggausmahdollisuudet.
Prologin deklaratiivinen koodi on "itsedokumentoivaa", helppolukuista sekä modulaarista, koska sovellus rakentuu pelkästään faktoista ja säännöistä ja niistä muodostetuista lausekkeista. Koodista pääsee yleensä suhteellisen nopeasti perille, kun on oppinut Prologin tavoille. Ohjelmointiparadigman erilaisuus totuttuun proseduraaliseen verrattuna on kylläkin kynnys, joka saattaa joskus hankaloittaa koodin lukua.
Myytti Prologin ylimaallisesta hitaudesta ei pitäne paikkaansa ainakaan Visual Prologin tapauksessa. Kuvassa 4.1. on tulokset eräästä QuickSort -lajittelutestistä. Visual Prolog jäi tosin viimeiseksi, mutta erot Pascaliin ja C++:aan eivät ole järisyttäviä . Yllättäen (?) C++ ei ollutkaan nopein vaan Pascal. C++:n hyytyminen johtunee luokkarakenteen käsittelyn hitaudesta.
Kuva 4.1. QuickSort-algoritmi Visual Prologille
DOMAINS list = integer* PREDICATES test tulosta(list) sort(list, list, list) split(list, integer, list, list) vert(integer, integer) CLAUSES test():- L=[6,3,4,2,8,10,2,5,6], %järjestettävä lista sort(L, [], A), tulosta(L), nl, tulosta(A), readchar(CH), !. tulosta([Head|List]):- write(Head), write(" ,"), tulosta(List). tulosta([]). sort([],S,S). sort([Head|Tail], SortedBigger, Result):- split(Tail, Head, LessList, BiggerList), sort(BiggerList, SortedBigger, NewSortedBigger), sort(LessList, [Head|NewSortedBigger], Result). split([],_, [], []). split([Y|L], X, [Y|L1], L2):- vert(X, Y), !, split(L, X, L1, L2). split([Y|L], X, L1, [Y|L2]):- not(vert(X, Y)), !, split(L, X, L1, L2). vert(X,Y):- X >= Y. GOAL test().
Tällä hetkellä Visual Prolog on saatavissa MS-DOS -käyttöjärjestelmälle, PharLab-Extended DOS, Windows 3.1, Win 3.11, Win 95 ja Win NT sekä OS/2 käyttöjärjestelmille.
VDE:n sisältämän käyttöliittymärajapinta-abstraktion VPI:n avulla on helppo laatia eri ympäristöihin siirrettäviä graafisia ohjelmia. Erilaiset koodigeneraattorit ja resurssieditorit mahdollistavat nopean protoilun nimenomaan käyttöliittymän suunnittelussa. VPI tarjoaa ohjelmoijan käyttöön keskeiset API-predikaatit Prolog-sovelluksen käyttöliittymän tekemiseen.
Dialogieditorilla dialogien luominen käy kätevästi. Mahdollisia kontrolleja on käytettävissä seuraavat (katso kuva 5.1): PUSH BUTTON, CHECK BOX, RADIO BUTTON, SCROLL BAR, STATIC TEXT, EDIT, CONTROL, LIST BOX, LIST BUTTON, LIST EDIT, GROUP BOX ja ICON. Myös omia CUSTOM -kontrolleja (esim. Prologilla luotu ikkunaluokka) on mahdollista lisätä.
Ikkunaeditorilla tehdyt ikkunat on suoraan siirrettävissä Prolog ohjelmaan ilman ohjelmointia.
Menueditorilla voidaan laatia päämenu ja alamenuja. Editorilla tehtyjä menuja voi testata kääntämättä sovellusta.
Työkalurivieditorilla laadituilla kontrolliriveillä voi olla normaalien kontollien (PUSH BUTTON, CHECK BOX, LIST BUTTON) lisäksi tekstikenttiä ja erottimia. Kontrolleihin on mahdollista liittää myös help-teksti, joka tulee näkyviin kursorin ollessa ko. kontrollin yllä.
Merkkijonoeditorilla luodut merkkijonotaulukot tallennetaan resurssitiedostoon. Resurssitiedostoon tallennettavia merkkijonoja ovat esimerkiksi sovelluksen antamat kehotukset ja virheilmoitukset.
Grafiikkaeditori on tarkoitettu pienien bittikarttojen (max. 64x64 pikseliä) luomiseen. Tällä Visual Prologin mukana tulevalla bittikarttaeditori voi tehdä lähinnä ikoneja, kursoreita tai muita bittikarttoja . Jos yrittää tehdä isoja bittikarttoja, niin Visual Prolog käynnistää automaattisesti MS Paintbrushin. Hypertekstikehitin (Help Maker ) on Visual Prologin oma editori avustusten tekemiseen. Se sisältää monipuoliset työkalut avustusten suunnitteluun, tekemiseen, kääntämiseen ja testaamiseen. Kääntäessään avustustiedostoja Windowsissa Help Maker käyttää MS Help Compileria.
Seuraavassa keskitytään erityisesti Visual Prologin integroituun ohjelmointiympäristöön (Visual Development Environment, VDE) ja tarkastellaan lyhyesti myös siirrettävää käyttöliittymärajapintaa (Visual Programming Interface). Sovelluksen rakentamisessa esimerkinomaisena sovelluksena käytetään yksinkertaista digitaalikelloa, joka koostuu dialogista, painonapista, tsekkausruudusta ja tekstikentästä.
Kuva 5.2. Sovellushallitsimen dialogi.
Sovellushallitsin tekee
Sovelluhallitsimen dialogissa (kuva 5.2) voidaan määritellä sovelluksen ajoympäristö (Windows/NT, OS/2 tai DOS) ja se, tehdäänkö ajettava sovellus vai DLL-kirjasto. Käyttöliittymätyypiksi voidaan valita jokin seuraavista:
Kuva 5.3. VPI-optiodialogi.
Projekti-ikkunaan voidaan valita näkyviin halutun tyyppiset resurssit. Kuvan 5.4 ikkunassa ovat näkyvissä `KELLO' -projektiin kuuluvat Prolog-tiedostot.
Kuva 5.4. Projektidialogi
Kun Projekti-ikkunassa (kuva 5.4) valitaan uusi ikkuna painikkeilla `Window-New', avautuu dialogi- ja ikkuna-asiantuntija (Dialog and Window Expert) (kuva 5.5).
Dialogi- ja ikkuna-asiantuntija osaa luoda oletuskoodin halutulle tapahtumalle. Tapahtumankäsittelijän (Event Handling) vasemmanpuoleinen valikko sisältää tapahtumatyypit ja oikeanpuoleinen mahdolliset tapahtumat (kuva 5.5).
Jos halutaan esimerkiksi generoida koodi ikkunan luonnille, valitaan `e_Create' ja `Add Clause' (ks. kuva 5.6).
Kuva 5.5. Dialog- ja ikkuna-asiantuntija.
Kuva 5.6. Koodiekspertin tuottama oletuspredikaatti ikkunan luonnille (lisätty omaa koodia).
Resurssien lisääminen ikkunaan tapahtuu valitsemalla Dialogi- ja ikkuna-asiantuntijassa `Layout'. Kuva 5.7 näkyy erilaiset kontrollit ja sommittelut, joita voi käyttää.
Kuva 5.7: Ikkunan sommittelua.
Tosin kyllä VPI:ssäkin komentoja löytyy n. 300, mutta koodigeneraattoreiden oletuskoodit auttavat paljon. Käyttäjä voi myös hakea Insert-komennolla minkä tahansa komennon määrittelymuodon ohjelmakoodiin. Usein haetun komennon muuttujaparametritkin ovat jo valmiiksi lähes oikein, joten koodin suoltaminen käy jopa aloittelijalta melko kivuttomasti.
Eräs ratkaisu ovat erilaiset sovelluskehittimet . Esim. jo taulukkolaskenta-, tietokanta- ja tekstinkäsittelyohjelmien makrokielillä on mahdollista tehdä vaativiakin sovelluksia varsinkin, kun eri sovelluskehittimien ominaisuuksia on mahdollista yhdistää esimerkiksi Windowsissa DDE-linkeillä. Joustamattomuus muodostuu kuitenkin aina jossakin vaiheessa sovelluskehittimien ongelmaksi. Sovellusalueen monimutkaistuessa perinteisten kehittimien resurssit loppuvat nopeasti.
Silloin kun sovelluskehitin ei enää riitä, on palattava takaisin yleisohjelmointikieliin. Edullisinta on todennäköisesti valita mahdollisimman korkeaa abstraktiotasoa edustava kieli, ellei tarvita selkeästi jonkun tietyn kielen erityisvahvuuksia (esim. c-kieli aikakriittisissä systeemitason sovelluksissa).
Prolog on varteenotettava vaihtoehto ohjelmointikieleksi, kun tarvitaan ilmaisuvoimaa ja korkeaa käsitetasoa. Visual Prologissa on pyritty yhdistämään Prolog-tulkki kokonaisvaltaiseen ohjelmankehitysympäristöön ála Delphi. Visual Prolog kääntäjä onkin varsin kehittynyt,eikä sillä tehtyjen reaalimaailman sovellusten ajamiseen enää tarvita epärealistisia supertietokoneita kuten Prolog-tulkeilla aikoinaan.
PDC (Prolog Development C enterin) Visual Prolog -projekti on kunnianhimoinen. Se kattaa kokonaisen ohjelmointiympäristön: välineet siirrettävien käyttöliittymien tekemiseen, erilaisia resurssieditoreja, ym. Sitä ei voi pitää pelkästään Prologin markkinointikikka, vaikka tämänhetkinen versio (Standard Version 4.0) ei vielä lunastakaan kaikkia lupauksia.
Toivomuslistalle laittaisin ensimmäiseksi jossain suhteissa kattavamman dokumentaation. Esimerkiksi C:llä tehtyjen DLL-kirjastojen kutsuminen ei onnistunut Visual Prologista edes parin päivän kokeilujen ja manuaalien selaamisenkaan jälkeen. Debuggaustyökalut ovat vielä pahasti hakusessa ja vajavaisia. Tulevissa versioissa pitäisi olla parannusta luvassa. Myös esilletulleiden bugien lista on VP:n version 4.0 Windows-versiossakin vielä luvattoman pitkä. Onneksi PDC:n kotisivun alta on imuroitavissa fiksaustiedostot ainakin havaituista bugeista.
[1] Borlandin ex-pääjohtajan, P. Kahnin, mukaan.