Sunday, September 23rd, 2012
Skriv en kommentar

I går skrev jeg en blogpost hvor jeg blant annet introduserte programmeringsspråket PogoScript. Dette språket fortjente litt mer eksperimentering, så jeg utvidet eksempelet litt, og har tenkt å vise det her.

Poenget med PogoScript – det som skiller språket fra alt annet jeg har sett – er at det enkelt muliggjør å skrive kode som nesten er normal engelsk (eller norsk for den del). Det er skjelden jeg ønsker å gå så langt som det PogoScript tillater, men om man får behov for å skrive kode som ikke-programmerer skal forstå, og man kan gjøre det i et språk som kompilerer til JavaScript, så er PogoScript en veldig interessant mulighet.

For eksempel kan jeg se for meg at man kan skrive enkelte forretningsregler i PogoScript. Et program skrevet i for eksempel C# for .NET kan så kompilere PogoScript-koden til JavaScript og eksekvere denne med med en interpreter (f.eks. Jint). Og hey presto: Du har et veldig fleksibelt system hvor forretningsfolk kan lese og forstå deler av koden, og til og med kan endre funksjonaliteten selv ved behov.

En DSLifisering av bowling-koden

Jeg har altså gjort et lite forsøk på å vise hvordan jeg kan gjøre koden min mere leselig for ikke-utviklere vha. PogoScript. Koden du får se beregner poengsummen for en bowlingserie. Den første funksjonen heter “total score for (game)”. game er parameteret til funksjonen – et array med de ulike kastene i serien.

total score for (game) =
    result = 0
    do the following once for every frame
        result = result +
        score of next frame in (game)

    result

Les koden! “Do the following once for every frame”. “Result = result + score of next frame in game”. Dette er ganske enkelt å forstå – om man kan bowling. “score of next frame in (game)” er en annen funksjon, og den kommer her:

score of next frame in (rolls) =
    if (first throw in (rolls) got all pins down)
        take the first pin count in (rolls) +
        the next two throws in (rolls)
    else if (first two throws in (rolls) got all pins down)
        take the two first pin counts in (rolls) +
        the next throw in (rolls)
    else
        take the two first pin counts in (rolls)

Dette ser ut som en beskrivelse, som såkalt pseudokode, men det er faktisk eksekverbar kode. Er det ikke kult? En utvikler vil kanskje ikke synes det er så veldig leselig, men en som ikke kan programmering vil forhåpentligvis kunne sette pris på det.

De to funksjonene over kaller en rekke andre funksjoner, som utgjør det vi kan kalle en DSL – et domenespesifikt språk for domenet bowling. DSL-funksjonen skjuler de teknsike detaljene. Og her er de:

do the following once for every frame (block) =
    for (i = 0, i < 10, i = i + 1)
        block()

first throw in (rolls) got all pins down =
    rolls.0 == 10

first two throws in (rolls) got all pins down =
    (rolls.0 + rolls.1) == 10

take the two first pin counts in (rolls) =
    rolls.shift() + rolls.shift()

take the first pin count in (rolls) =
    rolls.shift()

the next throw in (rolls) =
    rolls.0

the next two throws in (rolls) =
    rolls.0 + rolls.1

Skulle jeg faktisk ha brukt dette her hadde jeg nok gjort meg mere flid med oppbygningen av DSL’en, men koden her illustrerer i alle fall noen av mulighetene.

Til slutt kan jeg laget en tilfeldig bowlingserie og beregne score. Selv disse to linjene er veldig leselige – jeg tror Donald Knuth (opphavsmannen til Litterær programmering) ville vært stolt.

random game = [10,8,2,5,5,7,3,10,10,7,1,10,10,10,10,8]

console.log (total score for (random game))

Resultatet av dette skriptet er tallet 213.

Kategorier: DSL.
RSS feed for kommentarene. Tilbaketråkk.

2 kommentarer til “Mer eksperimentering med PogoScript”

  1. Johannes Brodwall Says:

    Oi, det var annerledes. Morsomt språk, men som du sier tror jeg at utviklere fort føler seg mer desorienterte enn ikke-utviklere, siden det krever litt mer å skille på nøkkelord og funksjonsnavn.

    Jeg tenkte: Den måten å ha “infix”-parametre minner litt om Smalltalk, synes du ikke?

  2. Torbjørn Says:

    Jo, på en måte minner det vel om Smalltalk. “What is unique about Smalltalk is its funny method invocation protocol. Method arguments are listed positionally, like in C or Java, but they must be preceded by the parameter name, and aren’t delimited by parentheses.” (sitat)

    I Smalltalk er det altså ikke det at du putter parametere hvor du vil i metodenavnet, men at navnene på parametrene er metodenavnet. Dette gir en lignende mulighet til å “bygge setninger”, men ikke like fleksibelt.

    For eksempel kan man si noe sånt som:

    person hasGivenName: "Tom" andSurname: "Jones"
    

    person er et objekt. hasGivenName:andSurname: er metoden (en sammensetning av de formelle parametrene). “Tom” og “Jones” er argumentene.

Skriv en kommentar

Tillatte tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Siste kommentarer

Torbjørn
PS: Takk til Børge Hansen, som delte SCARF-modellen med meg!...
Børge Hansen
Denne likte jeg veldig godt. Du skriver godt og har gode betraktninger  Keep it up – flere trenger å tørre å lære mer om ledelse – du l...
Tormod
Er egentlig ikke overrasket. F# sin fortè er programmererens produktivitet/kvalitet og anledning til parallell kjøring. Men kjøremotoren har ...
Stian
Ville også prøvd med et større problem (x100 eller x1000 f.eks). Når man snakker så små brøkdeler av et sekund som her så kan tiden for en ell...
Torbjørn
Har ikke sjekket - tar en titt i morgen hvis tid :)...
Einar W. Høst
Mhp tco: hva sier ILSpy?...
Torbjørn
Har ikke sett noe på PSeq før, men kjenner til den typen funksjoner fra blant annet Clojure. Og problemet med slike funksjoner i sammenhenger som de...
Håvard
Veldig bra sammenligning! Har du sett på ytelsen av PSeq.* fra powerpakken? Tipper den vil gi performancehit på små mengder, men kan kanskje resul...
Torbjørn
Jeg kom på en demonstrasjon-variant til jeg burde inkludere, nemlig bruk av list comprehension (en type computation expression (også kalt monads)). ...
Einar W. Høst
Interessant, det blir en trade-off mellom eleganse og fart på en måte. Den funksjonelle løsningen med vanlig filter er ren og pen, mens den imperat...
Creative Commons-lisens
Innholdet på denne bloggen er tilgjengelig under Creative Commons Navngivelse-Ikkekommersiell-DelPåSammeVilkår 3.0 Norge lisens.

Programmeringsbloggen
Kjempekjekt.com

© 2006-2013 Torbjørn Marø

Jeg har vært en profesjonell programmerer siden 1999, og dette er min blogg. Målet med bloggen er å stimulere meg selv og alle andre til kontinuerlig eksperimentering og læring.

Jeg forsøker å være allsidig, og programmerer blant annet i C#, Ruby, Erlang og Clojure.

Jeg praktiserer TDD og andre smidige utviklingspraksiser. Jeg er opptatt av kvalitet og ren kode.

Dette og ganske mye mer kan du lese om på denne bloggen!