Mer eksperimentering med PogoScript


søndag 23. september 2012 DSL

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.


comments powered by Disqus