(toiminnot)

hwechtla-tl: Scheme-käyttis

Kierre.png

Mikä on WikiWiki?
nettipäiväkirja
koko wiki (etsi)
viime muutokset


Scheme-käyttis on käyttöjärjestelmä, jossa kaikki (mahdollinen) on kirjoitettu Schemellä. Ajatuksen voi nähdä suorana jatkona 80-luvun Lisp-koneisiin, joissa kaikki oli kirjoitettu Lisp-kielellä. Oman järjestelmäni nimeksi ajattelin ottaa Yggdrasil.

Monista Scheme-käyttis voi tuntua aivan älyttömältä projektilta. Tyypilliset epäilyt jakautuvat kolmeen luokkaan: epäilyksiin kieliympäristön rajoittavuudesta, epäilyksiin tehottomuudesta, ja epäilyksiin siitä, että tällainen on aivan turhaa vaivannäköä, koska käytössämme on jo hyvin toimivia käyttöjärjestelmiä ja niiden uudelleentoteuttaminen on järjetön projekti. Puolustelen projektin oikeutusta ja järkevyyttä seuraavassa.

Ensinnäkin, on aivan järkevää perustaa kokonainen käyttöympäristö yhteen kieleen. Monikielisessäkin käyttöjärjestelmässä on pakosti jokin yhteinen kieli, jonka avulla muut kielet on määritelty. Yleensä se on konekieli. Yhden pakollisen kielen vinssaaminen konekielen päälle maksaa suoritustehossa (josta lisää myöhempänä), mutta sillä on saavutettavissa myös suuria etuja.

Scheme on hyvä kieli käyttöjärjestelmän perustaksi. Schemen viitesemantiikka ja sulkeumat tarjoavat yksistään hienovaraisemman suojaus- ja oikeusmekanismin kuin Unixin oikeusjärjestelmä. Koska Scheme on pieni ja elegantti kieli, sen semantiikkaa on myös helppo muuttaa mieleisekseen -- esimerkiksi lisätä perumishistoria jokaiselle toiminnolle. Kaikkien olioiden säilöminen muistiin vakioidussa muodossa mahdollistaa keskitetyn roskankeruun ja muisti-imagen käyttämisen tiedostojärjestelmänä, jolloin erillistä tiedostojärjestelmää ei tarvita. Se, että kaikille olioille on vakioitu tekstiesitysmuoto, helpottaa järjestelmän hajauttamista ja sovellustason verkkoprotokollien toteutusta. Scheme sisältää (keskeytyskäsittelyä lukuun ottamatta) kaikki primitiivit, joita tarvitaan moniajon toteuttamiseen.

Scheme on monipuolinen ja ilmaisuvoimainen kieli. Jotkin kielet ovat vielä ilmaisuvoimaisempia, esimerkiksi Prolog ja Haskell (joista jälkemmäinen tosin kärsii staattisen tyypityksen tuomista rajoituksista) sekä jotkin uudelleenkirjoituskielet, mutta näiden ilmaisuvoimaisempien kielten käytännöllisyys usein kärsii. Esimerkiksi on vaikeaa kuvitella, miten Haskellissa voisi järkevästi uudelleenmääritellä funktion kesken ohjelman suorituksen (aivan olennaista, jos haluat, että käyttöjärjestelmässäsi voi oikeasti kehittää mitään), ja hyödyllisten Prolog-debuggereiden kehittäminen on vaikeaa. Scheme ja Lisp tarjoavat kätevässä paketissa sekä ohjelmien suoritustason että metatason, jolla ohjelmia tarkastellaan.

Yhden kielen suosiminen ei tarkoita, etteikö muita kieliä voisi tukea. Esimerkiksi Unix on edelleen olennaisesti naimisissa C-kielen kanssa, mutta silti sitä voidaan pitää nykyään monikielisenä ympäristönä. (Unixissa on kaikenlaisia skriptikieliä sun muita, joiden toteutus on tyypillisesti kirjoitettu C-kielellä.) Myös muiden kielten kääntäminen Schemeksi on järkevää eikä usein itse asiassa kovin vaikeaa, koska Scheme tyypillisesti sisältää valmiiksi kaikki kohdekielen ominaisuudet.

Mutta edetkäämme tehokkuusepäilyihin. Myönnän auliisti, että konekielestä luopuminen hidastaa useimpia laskentasovelluksia. Toisaalta suurin osa tietokoneiden "asiallisesta" käytöstä ei ole laskentaa, vaan tekstinkäsittelyä, tietojen järjestelyä, kommunikointia muiden koneiden kanssa yms., jossa Schemen lisäabstraktioista on pikemminkin hyötyä kuin haittaa. Roskankeruun keskittäminen yhdelle järjestelmälle saattaa jopa nopeuttaa muistinhallintaa. On myös suuri etu, ettei Scheme-ohjelmia tarvitse suojata toisiltaan: näin prosessin sisäisen toiminnan hidastumisesta saadaan vastineeksi prosessien välisen kommunikaation nopeutuminen: kutsu "toiseen prosessiin" on ihan yksinkertainen funktiokutsu, joka ei ole sen hitaampi kuin prosessinsisäinenkään funktiokutsu. (Tämä arkkitehtuurivalinta Linuxin ytimessä yksinkertaisti ytimen toteutusta, teki siitä tehokkaan, ja nosti monoliittiset kernelit takaisin kunniansa kukkuloille.) Sama tilanne vallitsee ytimen ja prosessin välillä: systeemikutsu on vain tavallinen funktiokutsu, johon ei liity suojausringin vaihto tms.

Schemeä voi myös kääntää konekieleksi. Koska konekielen suoritus ei voi olla turvallista, on kääntämisprosessin oltava erityisoikeuksilla toimiva, luotettu palvelu. Tästä on myös etuja: jos kääntäjän läsnäoloon ja toimintaan voi luottaa, ydin voi kutsua sitä milloin tahansa halutessaan, esimerkiksi läpinäkyvästi funktiota kutsuttaessa. Tällainen ympäristö yhdistää skriptikielten muokattavuuden (ohjelmaa voi korjailla ja testata ohjelman sisältä) ja ainakin osan käännettyjen kielten tehosta.

Schemen kaltainen abstrakti, yksinkertainen kieli tekee helpoksi useammanlaiset toteutukset. Koko käyttiksen toimintatapaa voi muuttaa radikaalisti erilaiseksi ilman, että vanhat ohjelmat lakkaavat toimimasta.

Mutta kolmanteen kohtaan. Vaikka tällaisella käyttöjärjestelmällä olisikin näin paljon teknisiä etuja, maksaako sen tekeminen kuitenkaan vaivaa? Emmekö voi olla tyytyväisiä siihen, mitä meillä on -- sehän näyttää toimivan tarpeeksi hyvin? Olen tästä periaatteessa samaa mieltä, enkä toivokaan Scheme-käyttöjärjestelmän pyrkivän matkimaan olemassaolevia käyttöjärjestelmiä millään tavoin. Olisi yhtä helvettiä, jos esimerkiksi joutuisi kirjoittamaan SSL-toteutuksen sertifikaattisäätöineen, ncursesin tai vaikkapa OpenOfficen uudestaan. Pikemminkin Scheme-käyttis olisi kokeilu, miten asiat voi tehdä yksinkertaisesti ja kauniisti.

Monia hienojakin asioita voi tehdä hyvin suoraviivaisesti, kunhan keksii oikean tavan. Esimerkiksi graafisten käyttöympäristöjen tekemistä pidetään yleensä vaivalloisena ja hitaana, mutta hyvän suunnittelun, pitkän perinteen ja oikeanlaisen kehitysympäristön seurauksena Squeak loi lyhyessä ajassa paremman graafisen käyttöympäristön kuin mitä Windowsissa tai Macissa on. Toinen esimerkki yksinkertaistavasta suunnittelupäätöksestä on mainitsemani muistiavaruuden ja tiedostojärjestelmän yhdistäminen (ns. persistent swap). Scheme itsessään edustaa tätä "mahdollisimman vähällä mahdollisimman paljon" -ideologiaa. Itse asiassa Scheme on tavallaan kiteytys kaikesta siitä, mitä Lispistä ehdittiin oppia vuoden 1957 jälkeen aina 70-luvun lopulle asti. Lisp puolestaan orgaanisuutensa ja edistyksellisten kehitysympäristöjen vuoksi toimi alustana melkein jokaiselle ohjelmointiympäristöjen kehityskokeilulle.

Scheme on myös turvallinen kieli. Siitä huolimatta, että avoimien ohjelmistojen tulo on nyt taas kohottanut rimaa ohjelmistojen laadukkuudessa, turvapäivitykset sun muut ovat edelleen arkipäivää. C-ohjelmien turvarei'istä noin 70% johtuu mokista, joita Schemessä ei voi tehdä. Lopuistakin rei'istä monet ovat sellaisia, etteivät niiden vaikutukset Schemessä ole varsinaisesti vaarallisia. Turvallinen kieli tarjoaa hyvän perustan turvalliselle järjestelmälle.

Muuten, hauska esimerkki siitä, mitä Schemellä voi tehdä (tämä ei tosin ole ihan R5RS-pohjainen): jos haluan muistiin jokaisen määrittelyn sijainnin lähdekoodissa:

(define ur-define define)

(define-syntax define
  (syntax-rules ()
    ((define (fn . args) . body)
     (begin (ur-define (fn . args) . body)
            (mark-source-info! fn '(define (fn . args) . body))))
    ((define var value)
     (begin (ur-define var value)
            (mark-source-info! 'var '(define var value))))))

(define (mark-source-info! obj defn)
  (let ((p (current-load-port)))
    (hash-table-put! *source-info* obj
      (list (port-name p) (port-current-line p) defn))))

Tein tämän avulla tsydeemin, jolla voi REPL:stä käsin käydä editoimassa haluamansa funktion määrittelyä.

kategoria: projektit


kommentoi (viimeksi muutettu 12.07.2007 01:45)