Polyglot

En polyglot er en person som bruker to eller flere språk, og denne kategorien handler om å lære seg og bruke flere, ulike programmeringspråk.

COBOL

COBOL ble skapt i 1959, og er den dag i dag et av de viktigste språkene i utallige, kritiske forretningssystemer. COBOL er tungvindt, og COBOL gjør ting enkelt. COBOL er elsket, og COBOL er hatet. Jeg oppfordrer deg ikke til å bli en COBOL-utvikler, men alle seriøse utviklere bør vite hva COBOL er, hvordan et COBOL-program ser ut, og hvilket betydning det har hatt og fortsatt har.

COBOL

COBOL står for COmmon Business Oriented Language, og var et sammarbeid mellom U.S. Department of Defence og ulike datamaskinprodusenter, brukere og universiteter. Det ble designet for å løse typiske forretningsproblemer, være maskin-uavhengig, og utvidbart.

Sentralt i utviklingen av språket stod Grace Hopper, og du kan lese mer om henne og bakgrunnen for språket i julekalenderen fra i fjor.

COBOL skiller seg klart fra de andre overlevningene fra samme tidsperiode. Mens bruk av f.eks. FORTRAN krevde kunnskap om både matematikk og hvordan datamaskiner fungerer, rettet COBOL seg mer mot brukere med forretningsforståelse. Syntaksen er langt fra minimalistisk, og skulle i teorien være enklere å lese for “vanlige mennesker”.

Utbredelse

COBOL har hatt en enorm utbredelse. I 1997 rapporterte Gartner Group at 80% av “the world’s business” kjørte på COBOL, med over 200 milliarder linjer kode, og at antallet kodelinjer fortsatt økte med rundt 5 milliarder hvert år. Jeg antar at denne veksten har gått kraftig tilbake, blant annet takket være populariteten til Java og .NET. Men det er åpenbart at COBOL fortsatt spiller en veldig viktig rolle, og det står et ukjent antall stormaskiner rundt omkring i verden og eksekverer COBOL-linjer.

Bruken av COBOL har derimot vært omstridt. I 1975 bemerket Edsger Dijkstra at: “The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense.” Han sa forsåvidt det samme om BASIC også.

Litt kode

Det var veldig spennende å sette seg ned og forsøke å lære nok COBOL til å løse Euler-oppgaven. Og etter et par tutorials viste det seg å være ganske lett. Programmet ligner ikke mye på noen av de andre du har sett, men det er egentlig bare førsteinntrykket. For løsningen er rett og slett bare en for-løkke, en if-test og en oppsummering i en variabel.

Men for at du skal forstå hva du ser nedenfor må jeg forklare litt nærmere. Programmet består av ulike deler, kalt divisjoner. Identification-divisjonen inneholder metadata om programmet. I Data-divisjonen må jeg definere alle variablene jeg skal bruke, og i Procedure-divisjonen kommer selve algoritmen.

 1 000010 IDENTIFICATION DIVISION.
 2 000020 PROGRAM-ID.   EULER-1-PROG.
 3 000030 AUTHOR.       TORBJORN MARO.
 4 000040*Sum numbers below 1000 that's multiples of 3 or 5
 5 000050
 6 000080 DATA DIVISION.
 7 000090 WORKING-STORAGE SECTION.
 8 000100 01 N              PIC 9(4).
 9 000101 01 MOD-3          PIC 9.
10 000102 01 MOD-5          PIC 9.
11 000105 01 EULER-SUM      PIC 9(6) VALUE 0.
12 000110
13 000120 PROCEDURE DIVISION.
14 000130 MAIN-PARAGRAPH.
15 000140    PERFORM VARYING N FROM 0 BY 1 UNTIL N > 999
16 000142       COMPUTE MOD-3 = FUNCTION MOD (N, 3)
17 000143       COMPUTE MOD-5 = FUNCTION MOD (N, 5)
18 000150       IF MOD-3 = 0 OR MOD-5 = 0 THEN
19 000160           COMPUTE EULER-SUM = EULER-SUM + N
20 000165       END-IF
21 000170    END-PERFORM
22 000180    DISPLAY EULER-SUM
23 000190    STOP RUN.
24 

I linjen jeg har numerert 000105 sier jeg at EULER-SUM er en variabel som består av opp til 6 siffer – 9 betyr et heltall, og 6 i parantes betyr 6 stykker. “VALUE 0″ betyr at variabelen initielt settes til 0.

Linje 000140 er starten på en løkke som kjører fra 0 til og med 999. For hver iterasjon beregner jeg modulo N av 3 og 5, og hvis en av dem er lik 0 oppdaterer jeg i linje 000160 summen ved å legge til N.

Det var utrolig mye som måtte skrives for å oppnå veldig lite dette her :)

Hvorfor bruke tid på COBOL

Jeg har egentlig sagt det allerede – seriøse utviklere bør kjenne sin historie. Jeg vet ikke hvor mye praktisk nytte denne kunnskapen vil gi meg, men gjennom å gå inn for å lære meg litt COBOL – nok til å skrive denne artikkelen  – har jeg faktisk fått litt mere respekt for språket enn det jeg hadde i utgangspunktet. Og hvem vet, kanskje vil noen ha meg til å fikse litt på et COBOL-program en vakker dag, og jeg kan sitte der og håve inn 5000 kroner i timen!

COBOL har forresten også vært en viktig insirasjonsskilde til utviklingen av ABAP, et språk man bruker når man programmerer SAP. ABAP er i dag rangert som ett av de 20 mest populære programmeringsspråkene vi har.

Hvordan komme i gang

Du finner endel gamle men tilstrekkelige tutorials og lærebøker på nettet om du leter litt – for eksempel her og her. Det vanskeligste er å finne en COBOL-kompilator som du kan kjøre på PC’en din; de fleste COBOL-implementasjonene koster enten penger, er laget for stormaskiner, eller begge deler på en gang.

Om du har lyst til å forsøke deg på litt kode, men ikke orker å sette opp OpenCOBOL eller COBOL for GCC, så kan du jukse litt. Jeg brukte nemlig en site som heter ideone.com. Der kan du enkelt skrive og kjøre kode for et hav av ulike kompilatorer og tolkere, deriblant COBOL.

Betterave

Betterave er et såkalt esoterisk programmeringsspråk, sånn som Unlambda som jeg snakket om i luke 8, eller Brainf*ck som jeg skrev om tidligere i år. Men slapp av, det er ikke like grufullt som dem. Selv om Betterave ved første øyekast ser helt uforståelig ut, er det egentlig ganske enkelt. Så her har du et språk det er en stor sjangse for at du kan lære deg, og bruke til å imponere dine nerdevenner ;)

betterave

Betterave består av funksjonsuttrykk på samme måte som Lisp/Scheme. Språket har en prefix-notasjon, men ulikt Lisp slipper man alle parantesene – hver funksjon “vet selv” hvor mange parametre det har. Dermed kan man også trekke paralleller til Rebol, som egentlig fungerer på samme måte.

Litt kode

Og da skal du få se ditt første Betterave-program. Igjen finner jeg summen av alle tall under 1000 som er multipler av 3 eller 5. Siden ingen funksjoner i Betterave er lengre enn én bokstav får hele programmet fint plass på én linje:

 1 L-***83679N0S0[N+n1T+=0%n3=0%n5?>t0S+sn!|<nl].s

Enkelt, ikke sant? Du skjønte dette?

Som sagt, det er ikke så vanskelig som det ser ut – og å lære det er ganske givende. Mere givende enn å spille minesveiper eller soduku i alle fall, så da er det verdt tiden til de fleste av oss.

Selv om programmet kan skrives på én linje, så det ikke det. Ved å bryte det litt opp og legge på noen kommentarer tror jeg det skal være ganske enkelt å forstå hvordan det virker. Men du må vite et par ting først…

Tall

Det er ikke mulig å uttrykke tall som er større enn 9 i Betterave direkte. Når vi skriver 9 i koden er det egentlig en parameterløs funksjon som returnerer tallet 9, og siden ingen funksjoner kan bestå av mer enn ett tegn finnes det ingen 10-funksjon. Så hvordan lager jeg da for eksempel tallet 999, som jeg trenger for å løse oppgaven min?

Jo, jeg må regne litt! 8 ganger 3 er lik 24. I Betterave skrives det som *83. Altså funskjonskallet * (stjerne/multipliser) som tar to argumenter: resultatet av funksjonen 8 og resultatet av funksjonen 3.

Videre er 24 ganger 6 lik 144. Dette kan jeg nå uttrykke som **836. Og ganger jeg dette med 7, og trekker fra 9, så står jeg igjen med 999. Funksjonsuttrykket blir da –***83679.

Variabler

I Betterave har programmene tilgang til å bruke 27 variabler, en for hver bokstav i det engelske alfabetet. Stor bokstav, for eksempel A, er en funksjon som tar ett argument og lagrer argumentet som verdi i variabelen. Liten bokstav, for eksempel a, er en funksjon uten parametre, som returnerer verdien i variabelen.

Nå har du lært nesten alle tingene jeg har brukt i programmet du så i starten. Det eneste som manger er muligheter for å ta avgjørelser og å lage løkker.

Programflyt

Jeg har brukt to strukturer for programflyt i programmet mitt. Den første er [ xxx | yyy ]. Den fungerer sånn at hvis yyy er noe annet enn verdien 0, så hopper programmet tilbake til startklammen – altså [. Det er altså en veldig enkel do-while løkke.

Den andre strukturen er ? xxx yyy !. Denne fungerer sånn at hvis verdien av xxx er 0 så vil programmet hoppe til utropstegnet, og altså ikke evaluere yyy. Dette er altså en enkel if-setning.

Kildekoden med struktur og kommentarer

Hvis du har fulgt med skal du nå være i stand til å forstå det hele:

10 L -***83679       ~ storing 999 in L (limit)      ~
11 N 0               ~ setting N to 0                ~
12 S 0               ~ setting S (sum) to 0          ~
13 
14 [                 ~ loop                          ~
15   N +n1           ~ increment N                   ~
16 
17   ~ set T to the sum of the modulo tests          ~
18   T + =0%n3 =0%n5
19 
20   ? >t0           ~ if T is larger than 0         ~
21     S+sn          ~ add N to S (sum)              ~
22   !               ~ end if ~
23 |
24   <nl             ~ while N is less than L (limit)~
25 ]                 ~ end loop                      ~
26 
27 .s                ~ print value of S              ~

Jeg sa jo at det var enkelt!

Hvorfor bruke tid på Betterave

Du skal bruke tid på Betterave og andre esoteriske programmeringsspråk fordi det gjør at du må tenke. Dette er rett og slett problemløsning hvor du tvinges til å sette deg inn i et sett med regler, og hvor du må finne ut hvordan du får systemet disse reglene representerer til å gjøre noe for deg. Dette stimulerer deg og gir deg ferdigheter du som en utvikler behøver.

Dessuten er det gøy!!!

Hvordan komme igang

All informasjon du behøver om Betterave finner du på esolangs.org. Denne wikien er også en god kilde til andre, lignende språk du kan forsøke deg på.

Selve tolkeren til Betterave er skrevet i Ruby, og er ikke mange linjene. Jeg måtte modifisere den litt for at den skulle virke slik som jeg ønsket (dvs. at den kunne ta en betterave-fil som et argument og så kjøre denne), og min versjon finner du her. Har du Ruby installert allerede er det bare å lagre ned koden, og så kan du kjøre betterave-filer ved å sende dem til tolkeren i kommandolinjen din.

Rebol

Er du en rebell som stiller spørsmål ved etablerte sannheter? Da er kanskje REBOL et programmeringsspråk for deg. Rebol gjør opprør mot kompleksiteten vi ser i dagens software og språk.

rebol

REBOL står for Relative Expression Based Object Language. Første versjon kom i 1997, utviklet av selveste Carl Sassenrath, som var arkitekten og primær utvikler av AmigaOS i sin tid, og som i 1985 introduserte multitasking til PC-verden.

(Denne artikkelen omhandler REBOL 2. REBOL3 er en komplett omskrivning som har vært under utvikling en stund nå, og som har en god del endringer, men er fortsatt i alpha.)

REBOL setter enkelhet i høysetet. Det har i grunnen mange likheter med Lisp – det er symbolsk og homoikonisk for dem som skjønner hva det innebærer – men er likevel et mere moderne språk enn Lisp. Språket er dynamisk og sterkt typet. Det støtter flere programmeringsparadigmer, og har blant annet prototype-basert objektorientering (sånn som JavaScript).

Plattformen – om man kan kalle det det – er veldig liten og kompakt (dokumentasjonen sier ultra-kompakt), og programmene man lager blir også overraskende små.

Her ser du en figur som viser hvilke språk som har influert REBOL, og det faktum at REBOL var en viktig inspirasjonsskilde for JSON:

rebol_legacy

Hva kan man bruke REBOL til?

Et av hovedfokusene i REBOL er nettverkskommunikasjon og distribuerte løsninger. Det legger også vekt på utvikling av domenespesifike språk og meta-programmering. REBOL inkluderer grafisk brukergrensesnitt (GUI) som er likt på tvers av plattformer, funksjoner for bildemanipulering, parsing, komprimering, sikre nettverkstjenester, lyd, en database og mye mer.

Du kan bruke REBOL til å lage desktop applikasjoner, dynamiske web apps og server-tjenester, mobilapplikasjoner m.m. Det inkluderer også noe som nesten må betegnes som et virtuelt operativsystem:

“REBOL can also be used immediately, without installation, on over 40 operating systems as a lightweight file manager, text editor, calculator, database manager, email client, ftp client, news reader, image viewer/editor, OS shell, and more. You can use it as a simple utility program with a familiar interface to common computing activities, on just about any computer, even if you’re unfamiliar with the operating system.”

På tide med litt kode

Som vanlig var det første jeg gjorde i REBOL å implementere en løsning på Eulerproblem nummer 1. Helt uten forkunnskaper tok det meg kun 10-12 minutter å implementere en fungerende løsningen som du ser nedenfor:

10 REBOL [ Title: "Euler Problem #1" ]
11 
12 dividable-by: func [x y] [ 0 = modulo x y ]
13 
14 dividable-by-3-or-5: func [x]
15 [
16   (dividable-by x 3) or (dividable-by x 5)
17 ]
18 
19 sum: 0
20 repeat i 999
21 [
22   if dividable-by-3-or-5 i
23   [
24     sum: sum + i
25   ]
26 ]
27 
28 alert to-string sum

Den første linjen er en obligatorisk REBOL-header som kan inneholde diverse metadata om programmet. diviable-by er den første funksjonen som sjekker om et tall x er delelig på et tall y. dividable-by-3-or-5 bruker nevnte funksjon til å sjekke om x er delelig på 3 eller 5.

Jeg definerer så en variabel sum, og kjører en løkke fra 1 til 999 hvor jeg legger alle tall som er delelige på 3 eller 5 til sum. Til slutt åpner jeg en dialogboks / alert-vindu som presenterer svaret.

All indentering og alle linjeskift er forresten helt valgfrie, og har ingen betydning. Jeg kunne ha skrevet programmet på én linje om jeg hadde villet, men koden hadde selvsagt ikke vært så lesbar da.

En funksjonell løsning

Koden over var en imperativ løsning på oppgaven. Etter å ha studert språket litt ville jeg også forsøke å lage en løsning lignende den stream-baserte løsningen jeg presenterte i posten om Eulerproblemet.

REBOL egner seg greit for denne typen programmering (viste det seg), men inneholder derimot ikke de forventede funksjonene som range, filter, map og reduce out-of-the-box. Derfor lagde jeg dem selv.

Koden nedenfor illustrerer flere aspekter ved REBOL; de tre funksjonene range, filter og fold (“reduce” var opptatt og betyr noe annet i Rebol) er plassert som metoder på et prototype-objekt som jeg kaller fp (for funksjonell programmering). Jeg har også endret implementasjonen av dividable-by-3-or-5, og i den nøstede avslutningen av scriptet – som i praksis er Lisp-kode uten paranteser – bruker jeg en anonym funksjon.

10 REBOL [ Title: "Euler Problem #1, Functional style" ]
11 
12 ; Using prototype as namespace..
13 fp: make object! [
14   range: func [a b] [
15     r: copy []
16     for x a b 1 [ append r x ]
17   ]
18   filter: func [predicate list] [
19     new-list: copy []
20     foreach x list [
21       if predicate x [ append new-list x ]
22     ]
23   ]
24   ; Also known as reduce, collect, inject, aggregate
25   fold: func [initial f list] [
26     acc: initial
27     foreach x list [ acc: f acc x ]
28   ]
29 ]
30 
31 dividable-by-3-or-5: func [x] [
32   any [ zero? modulo x 3
33         zero? modulo x 5 ]
34 ]
35 
36 ; Barely readable, almost lisp but without parentheses :)
37 alert to-string
38       fp/fold 0 func[acc x] [ acc + x ]
39               fp/filter :dividable-by-3-or-5
40                         fp/range 1 999

Kontrollspørsmål til leseren: Hva returnerer range-funksjonen? Den returnerer selvfølgelig en liste med tall, men hvordan? En funksjon i REBOL returnerer resultatet av det siste uttrykket, og det er en for-løkke. For-løkken gjør det samme, den returnerer (eller evaluerer til om du vil) resultatet av det siste uttrykket i siste iterasjon – og det er funksjonskallet append. Append legger et element til en liste, og returnerer selve listen (altså r). Derfor returnerer range listen r, som bygges opp i for-løkken.

Samme teknikk benyttes også i filter og fold, og gjør koden kompakt og elegant.

En grafisk løsning

Rebol inneholder en egen dialekt – en intern DSL – for å lage grafiske brukergrensesnitt. Dette gjør det veldig enkelt å lage GUI. Min siste løsning viser hvordan jeg lager et lite vindu med en knapp som viser resultatet når man klikker på den.

10 REBOL [ Title: "A Visual Euler1 solution" ]
11 
12 euler1: does [
13   use [sum] [ sum: 0
14     repeat i 999 [
15       if any [ zero? modulo i 3
16                zero? modulo i 5 ] [
17         sum: sum + i
18       ]
19     ]
20   ]
21 ]
22 
23 view layout [
24   backcolor white
25   header: h1 "Euler #1"
26   button "Calculate answer" 180 [
27     header/text: to-string euler1
28     show header
29   ]
30 ]

Og slik ser det ut når programmet kjøres, før og etter at knappen trykkes:

eulerGUI

Hva er ikke så bra med REBOL, og hva er alternativet?

For det første: Bare deler av REBOL er open source, og språket finnes både i en gratis-utgave og i en betalt versjon med kommersiell support. For noen kan dette være problematisk og “skummelt”. Men gratisutgaven kan benyttes kommersielt, nesten uten noen restriksjoner.

REBOL har dessuten begrenset støtte for multithreading, og dette kan by på utfordringer for enkelte bruksområder.

En ting som kan være litt skummelt i Rebol er at variabler du oppretter inne i funksjoner er tilgjengelig i det globale “scopet” – samme utfordring som i Lua eller JavaScript egentlig (om man der glemmer “local” eller “var”). I det grafiske eksempelet unngikk jeg problemet ved å bruke use-funksjonen til å deklarere sum-variabelen, som da kun vil eksistere inne i use-blokken. Det finnes flere andre måter å gjøre dette på – men vær obs på at problemet er der.

I det funksjonelle eksempelet tok jeg ikke hensyn til dette, og introduserte variablene r, new-list og acc til det globale navnerommet uten at det var tiltenkt!

Litt sært?

Det største problemet ifølge enkelte er likevel at REBOL-communitiet er litt sært. Det kan virke som om filosofien bak språket har gått folk til hodet! Die-hard REBOLere bruker vistnok ikke det vanlige Internettet – det er for stort og komplekst – REBOL-baserte nettverk foretrekkes. Carl Sassenrath har OGSÅ nektet å bruke Subversion til REBOL-koden fordi han ikke vil bruke et system som er 50 ganger større og mer komplekst enn REBOL er i seg selv (les Fight Software Complexity Pollution).

Disse tingene har ført til utviklingen av et nytt open-source programmeringsspråk som er basert på REBOL. Dette heter Red, og har vært under utvikling i et drøyt halvår. Det skal gi deg det meste av hva REBOL har, men i tillegg ha støtte for parallellisering gjennom actors, støtte lavnivå systemprogrammering ala C med inline assembly, og være lett å embedde i andre systemer (som Lua). Det vil også legge vekt på å ha et godt IDE med gode debuggings-muligheter, og spåket vil ha en statisk kompilator og en JIT-kompilator.

Hvordan komme igang

Naviger til www.rebol.com og last ned siste versjon av REBOL/View for din plattform. Når du starter programmet får du opp en slags desktop hvor du kan navigere deg gjennom et hav av eksempler som du kan kjøre og studere kildekoden til.

Rebol_env

For å begynne å kode er det aller enkleste å lage en ny tekstfil med navn som ender på “.r”. Vim er en av flere editorer som har støtte for REBOL-syntaks, men støtten er strengt tatt ikke nødvendig. Og er du på Windows som meg kan du eksekvere r-filene direkte for å kjøre programmene.

Måten jeg begynte å lære var at jeg åpnet siden Learn REBOL, og rett og slett søkte og skumleste meg frem til det jeg trengte for å løse min første oppgave. Det kan hende min erfaring fra bl.a. Lisp og Forth hjalp meg endel. Etterhvert kan du lese det mere nøye, og i tilleg støtte deg på REBOL Function Dictionary, en API-referanse for enkeltfunksjoner.

Går du virkelig inn for full indoktrinering kan du gå igang med online-boken REBOL/Core Users Guide. Du finner alt dette og mye mer på REBOL Documentation-siden.

Konklusjon

REBOL er kompakt, praktisk, portabelt, produktivt, og sist men ikke minst anderledes! REBOL peker nese til moderne mainstream-språk, og hevder at det alle andre gjør er feil. Det hevdes at REBOL er enkelt å komme igang med, at selv vanlige folk uten programmeringsbakgrunn raskt kan lage nyttige og kraftige verktøy og scripts, og at profesjonelle utviklere heller ikke vil finne noen spesielle mangler i språket/miljøet.

Jeg har lekt meg endel med REBOL nå, og må innrømme jeg er ganske fasinert – språket er absolutt elegant. Det er litt som en “Lisp Light”, og det er bra. Jeg vil ha mer!

Noen av tingene jeg har sett på er blant annet hvordan man kan kjøre rebol på Windows i IIS, og hvordan man kan lage kode-genererende add-ins til Visual Studio – begge deler er fullt mulig.

Avslutningsvis, hvis du vil vite mer: her har du en link til en times-lang video hvor Carl Sassenrath forteller om språket sitt. Enjoy!

Smalltalk

Det finnes en håndfull språk som har hatt en enorm betydning for utviklingen av programmeringsspråk generelt. Jeg tenker da på språk som Algol, Lisp og C. Et annet språk som vi er nødt til å inkludere er Smalltalk – utviklet av Alan Key og Dan Ingalls med flere ved Xerox PARC på 60/70-tallet.

smalltalk

Smalltalk har påvirket oss på fire hovedområder: For det første har det influert syntaksen og semantikken til mange programmeringsspråk som har kommet senere – de som vises i figuren nedenfor er kun et lite utvalg. For det andre var Smalltalk en prototype på en programmeringsstil jeg har snakket om tidligere som kalles message passing style – en viktig modell for god objektorientert programmering (det var Alan Key som “fant opp” OOP-begrepet).

For det tredje inspirerte brukergrensesnittet utviklingen av grafiske operativsystem. Vinduene i den første Macintoshen var så og si identiske med vinduene i Smalltalk-80, den første offisielle releasen av språket. Og til slutt har Smalltalks integrerte utviklingsmiljø inspirert utviklingen av det vi i dag kjenner som IDE’er; visuelle programmeringsverktøy med kodebrowsere, debuggere osv.

smalltalk_legacy

Smalltalk er et minimalistisk og elegant språk. Absolutt alt er objekter, og syntaksen er enkel og konsis. Som i Lisp finnes det ingen spesielle strukturer eller kodeord for å lage løkker eller ta avgjørelser – alt er kun metodekall, eller “sending av meldinger til objekter” som Smalltalkere sier.

Integrert utviklingsmiljø

Smalltalk skiller seg nok fra de språkene du har brukt før ved det spesielle utviklingsmiljøet. Man koder ikke Smalltalk i tekstfiler som så enten tolkes eller kompileres for å kunne kjøre programmet. Smalltalk er et program i seg selv, som kjører hele tiden. Objektene lever i minnet, og man kan bruke en utforsker til å studere dem og endre dem.

Når man avslutter Smalltalk lagres alt sammen i et image; vi sier at Smalltalk er et image-basert utviklingsmiljø. Du kan lagre flere images, som i praksis blir ulike versjoner av Smalltalk, hvor du har gjort forskjellige endringer i hver av dem. Når du starter opp laster du ett av disse, som da altså både er språket, utviklingsmiljøet og programmet ditt.

Versjonen av Smalltalk som jeg har brukt har i tillegg til diverse utforskere, debugger og lignende også integrerte tutorials, integrert enhetstesting (SUnit) og støtte for avansert refakturering.

Og nå er du sikkert klar for litt kode

Som forklart tidligere forsøker jeg å løse Euler problem nummer 1 i alle nye språk jeg tester ut – altså hvordan man finner summen av alle tall under 1000 som er multipler av 3 eller 5. Her følger min første løsning i Smalltalk:

 1 ((1 to: 999) select: [:x |
 2   ((x rem: 3) == 0) | ((x rem: 5) == 0)
 3 ]) fold: [:memo :x | memo + x].

Jeg oppretter først et intervall fra 1 til 999. Så sender jeg meldingen select: til dette intervall-objektet, og sender med en kodeblokk som argument. Resultatet er at intervallet filtreres og jeg står igjen med en kolleksjon av tall som er multipler av 3 eller 5. Til slutt sender jeg meldingen fold: til kolleksjonen med en ny kodeblokk som plusser tallene sammen.

Sammenlign dette med denne løsningen i Ruby:

2 (1..999).select {|x|
3   x.modulo(3) == 0 or x.modulo(5) == 0
4 }.reduce {|memo, x| memo + x}

Likheten bør være tydelig. Ruby er nok det språket som er nærmest Smalltalk i dag. Det er noen syntaksforskjeller, spesielt knyttet til hvordan man sender meldinger til objekter (med dot-operatoren i Ruby), men ellers er disse to løsningene egentlig helt like.

Etter å ha browset litt i objektene i Smalltalk klarte jeg å rafinere løsningen litt, og kom opp med dette:

 5 ((1 to: 999)
 6   select: [:x | (x isDivisibleBy: 3) or: (x isDivisibleBy: 5) ]) sum

Det viste seg altså at Number-objektene allerede hadde en isDivisibleBy-metode (oppdaget dette da jeg skulle til å lage den selv), og at Collection hadde en sum-metode. Generelt sett har Smalltalk et veldig rikt API som har blitt bygget opp gjennom mange år.

Om du ikke er helt komfortabel med denne koden fordi det skjer mye på en gang har jeg brytt det opp litt for at det skal bli enklere å fordøye. Nedenfor lager jeg to temporære variabler: filter og range. Og så løser jeg oppgaven steg for steg, før jeg til slutt skriver ut svaret i det såkalte Transcript-vinduet (mer om det snart).

10 | filter range |
11 range := (1 to: 999).
12 filter := [:x | (x isDivisibleBy: 3) or: (x isDivisibleBy:  5)].
13 range := range select: filter.
14 range := range sum.
15 Transcript show: range.

Mer om utviklingsmiljøet

Det finnes en rekke open source-versjoner av Smalltalk. Squeak er kanskje den mest kjente, og er mye brukt til undervisning. GNU Smalltalk er ikke et komplett Smalltalk-miljø, men tilbyr i stedet en mer tradisjonell tolker for Smalltalk-kode. Amber er en Smalltalk-implementasjon laget i JavaScript, og gjør mye samme nytten som CoffeeScript som jeg snakket om i en tidligere luke.

Jeg valgte derimot å bruke en Smalltalk som heter Pharo, som kjører på Unix/Linux, MacOS og Windows, og ser helt likt ut alle steder. Nedenfor ser du et screenshot av hvordan det ser ut i bruk. Det du ser er en slags desktop med flere vinduer. Vinduet øverst til venstre er et arbeidsområde hvor jeg har skrevet litt kode (løsningen på oppgaven vår). Under dette vinduet er Transcript-vinduet, hvor jeg skriver ut resultatet.

Vinduet til høyre er en klasse/objekt-browser: Her har jeg navigert meg frem til isDevisableBy-metoden på Number-klassen. Selve koden for metoden vises nederst. Her kan jeg også foreta endringer om jeg ønsker det.

SmallTalk_Euler

Smalltalk’s grafiske brukergrensesnitt lar deg kommunisere med objektene dine på en mye mer direkte måte enn hva som er mulig i de fleste andre programmeringsspråk. Dette bør du oppleve!

Kulturkonflikt

Om du er en Java, C#, C++ –utvikler eller lignende så er Smalltalk-verden i konflikt med deg. Smalltalkerne sier det er de som driver med ekte objektorientering, C++ er ikke orntlig OO. Smalltalk var trolig også en viktig drivkraft og inspirasjonsskilde til den smidige revolusjonen for ca 10 år siden. Flere kjente Agile-forkjempere drev med Smalltalk, som for eksempel Martin Fowler, og Kent Beck, mannen bak TDD.

Smalltalk hadde sin storhetstid, men så tok det slutt. Kanskje det var det at de følte seg bedre enn alle andre? C++ dro i alle fall fra, og ble for en liten periode en defacto standard for objektorientering. Siden har andre språk som Ruby kommet til, og plukket opp igjen arven fra Smalltalk.

Så hvordan er Smalltalk forskjellig fra C++?

Vel, det er mange forskjeller. Smalltalk er dynamisk, C++ er statisk. Smalltalk er laget med utvikleren i fokus, mens C++ er sterkere knyttet til datamaskinen, og hvordan den fungerer. Men for å forstå Smalltalk er det spesielt to sentrale ting du må vite:

For det første: ALT ER OBJEKTER! Absolutt alt! C++ har mye som ikke er det; grunnleggende datatyper, klasser, kontrollstrukturer osv. Men i Smalltalk er alt bygget på samme lest, og samme hvor langt du graver finner du objekter.

For det andre: ALL KODE HAR ÉN FAST KONSEPTUELL FORM: object messageSentToIt. All koden du skriver i Smalltalk sender meldinger til objekter!

Og Smalltalkerne sier at hvis du ønsker å fortsette å kode i C++, eller Java, eller C#, så må du forsikre deg om at du aldri forstår hva disse to tingene betyr og innebærer. Hvis det begynner å gi mening for deg så må du slutte å lære deg Smalltalk med en eneste gang, for det finnes ingen vei tilbake :D

Er Smalltalk verdt å bruke tid på?

Ja, det er det. Smalltalk er historisk viktig, spesielt innenfor utviklingen av objektorientert tankegang. Utviklingsmiljøet er også fasinerende, og noe det er verdt å bruke tid på å forstå. Om du aldri kommer til å bruke Smalltalk til noe fornuftig, er det likevel berikende å se hvordan det fungerer.

Og om du liker det, men ønsker å bruke et mere levende språk som støttes av et aktivt community, så kan du jo gå over til Ruby etterpå!

Hvordan komme igang

Jeg foreslår du laster ned Pharo og bare fyrer det opp – ingen installasjon er nødvendig. I Pharo vil du finne en integrert, interaktiv tutorial som vil få deg så smått igang. Du kan også ta en titt på boken Pharo by Example, som kan lastes ned som PDF.

Lykke til!

CoffeeScript

CoffeeScript er et rykende ferskt språk som rett og slett forsøker å fikse alle problemene med JavaScript. Koden kompileres ned til JavaScript, og har en syntaks inspirert av Ruby, Python og Haskell. CoffeeScript gir deg som webutvikler også noen nye muligheter som list comprehensions, pattern matching, og klasse-basert objektorientering.

coffeescript_legacy

CoffeeScript er mye mer kompakt og elegant enn JavaScript, og har blitt godt mottatt av mange utviklere. Språket er blant annet inkludert i Ruby on Rails, og er også mye brukt på serversiden i Node.js. For noen måneder siden gikk også utviklingsteamet mitt over fra JavaScript til å skrive CoffeeScript, uten nevneverdige problemer.

coffeescript

CoffeeScript-compilatoren er skrevet i JavaScript, og selve kompileringen av scriptene kan derfor skje i browseren. Men dette er selvsagt ikke optimalt – det normale er at man som en del av build-prosessen genererer JavaScript-filer fra CoffeeScript’ene.

For .NET, som er vår plattform, finnes det også HTTP-handlers som kompilerer CoffeeScript on the fly, og server ut JavaScript. Dette er veldig praktisk under selve utviklingen.

La oss se på litt kode

Da er det på tide å løse Euler1-oppgaven igjen. Jeg skriver her CoffeeScript-kode som jeg tenker vil bli konvertert til JavaScript og plassert i en webside. Svaret vises ved hjelp av en alert-box.

Her er en enkel, imperativ kodesnutt som finner summen av alle multipler av 3 eller 5 under 1000:

 2 answer = 0
 3 for n in [1...1000]
 4   if n % 3 is 0 or n % 5 is 0
 5     answer += n
 6 alert answer

Koden kompileres til JavaScript’et nedenfor. Her ser du at CoffeeScript blant annet har “ranges” man kan iterere over, og  at koden bruker ord som is og or for å bli mere leservennlig. Du kan også se at den kompilerte koden følger best practises, og er wrappet inn i et funksjonskall, slik at det ikke opprettes noen variabler i det globale navnerommet.

10 (function() {
11   var answer, n;
12   answer = 0;
13   for (n = 1; n < 1000; n++) {
14     if (n % 3 === 0 || n % 5 === 0) {
15       answer += n;
16     }
17   }
18   alert(answer);
19 }).call(this);

Nedenfor har jeg laget en løsning til, som viser hvordan man oppretter funksjoner i CoffeeScript. Den bruker også en if bak et uttrykk, en teknikk arvet fra Ruby. Og numbers-variabelen settes ved hjelp av en list comprehension som utfører selve filtreringen.

10 multipleOf = (n, d) -> n % d is 0
11 
12 multipleOf3or5 = (n) ->
13   for divisor in [3,5]
14     return yes if multipleOf(n, divisor)
15 
16 numbers = (n for n in [1...1000] when multipleOf3or5 n)
17 
18 answer = 0
19 answer += n for n in numbers
20 alert "The answer is #{answer}!"

Den nest siste linjen som summerer opp tallene er også litt snedig, og den aller siste linjen viser at CoffeeScript støtter string interpolation. Og å kunne returnere “yes” i stedet for true fra multipleOf3or5 er jo også litt søtt da :)

Prototyping og monkey patching

JavaScript er jo et språk som støtter prototype-basert objektorientering. Her viser jeg hvordan jeg kan bruke dette i CoffeScript for å løse Euler1-oppgaven. Først oppretter jeg en isMultipleOf-metode på alle tall. Deretter kan jeg lage en fin multipleOf3or5-funksjon som bruker dette.

24 Number::isMultipleOf = (d) -> this % d is 0
25 
26 multipleOf3or5 = (n) ->
27   n.isMultipleOf(3) or n.isMultipleOf(5)
28 
29 Array::sum = ->
30   answer = 0
31   answer += n for n in this
32   return answer
33 
34 alert do (n for n in [1...1000] when multipleOf3or5 n).sum

Den tredje funksjonen opprettes som en metode på Array – den summerer opp alle tallene i arrayet. Til slutt bruker jeg list comprehension til å filtrere en range, og så kalle sum-metoden jeg lagde på resultatet.

Klasse-basert abstraksjon

CoffeeScript introduserer også en abstraksjon for klasse-basert objektorientering. Dette lar deg implementere klasser tilnærmet slik man gjør det i språk som f.eks. Ruby, og kompilatoren gjør dette om til prototype-basert JavaScript-kode.

Her følger klassen EulerProblem1 som har en kontruktør og to metoder. @limit og @sum er instansvariabler – den siste brukes til a cache resultatet av kalkuleringen. Selv om jeg sier calculate flere ganger vil selve kalkuleringen bare skje én gang slik jeg har valgt å gjøre det.

38 class EulerProblem1
39   constructor: (@limit) -> @sum = null
40 
41   include: (n) -> n % 3 is 0 or n % 5 is 0
42 
43   calculate: ->
44     if not @sum?
45       @sum += n for n in [1...@limit] when @include(n)
46 
47 ep1 = new EulerProblem1 1000
48 do ep1.calculate
49 alert ep1.sum

I de tre siste linjene ser du hvordan jeg oppretter en instans av klassen, hvordan jeg kaller metoden calculate, og hvordan jeg henter ut summen.

Hvorfor bruke tid på CoffeeScript

De fleste av oss har et forhold til JavaScript. Dette forholdet er gjerne litt ambivalent. JavaScript blir viktigere og viktigere for å kunne tilfredstille de økte forventningene til dagens webløsninger, men JavaScript er et språk med mange svakheter. Da er det interessant at man ikke kode i JavaScript direkte, men kan velge et renere og rikere språk som “kompileres” til JavaScript.

Det er viktig å poengtere at du kan benytte alle JavaScript-biblotekene du er vandt med også i CoffeeScript.

Er du Python- eller Ruby-utvikler er det nesten garantert at du kommer til å like CoffeeScript bedre enn JavaScript. Du bør uansett forsøke det, og så vurdere om det er verdt å legge denne ekstra abstraksjonen over JavaScript i akkurat ditt tilfelle.

Kan man bruke Coffee uten å kunne JavaScript?

Svaret på dette spørsmålet er desverre nei. Det finnes ikke enda (så vidt jeg vet) noen måte å debugge CoffeeScript på. Får man problemer vil man derfor få behov for å se på og debugge den genererte javaScript-koden. Koden er derimot helt grei, så dette er ikke et stort problem. Men man må kunne JavaScript!

Hvordan komme igang

Den offisielle CoffeeScript-siden finner du her. Den har en god primer som side-ved-side sammenligner CoffeeScript og JavaScript. Der kan du også teste språket direkte i browseren din.

Mye av det som finnes for å ta i bruk CoffeeScript er tilrettelagt for Linux og node.js-brukere. Hvis du er en Windows-bruker bør du ta en titt på CoffeeSharp, som gir deg det meste av hva du trenger.

Oz

Oz er et programmeringsspråk som skiller seg ut i mengden! Det er utviklet i et sammarbeid mellom flere universiteter, brukes først og fremst til undervisning, og støtter mange ulike programmeringsparadigmer som logisk programmering, funksjonell programmering, imperativ og objektorientert programmering osv. Det støtter samtidighetsbasert programmering blant annet gjennom bruk av actors, og er spesielt tilrettelagt for å lage distribuerte systemer.

oz

I bunn er Oz et meget enkelt språk med kun noen få datatyper. I tillegg har det en masse “syntaktisk sukker” som gjør språket praktisk. Det er først og fremst inspirert av Lisp, Prolog og Erlang, men har også skapt noe nytt og unikt.

Oz har derfor lenge fristet meg. Jeg har vurdert det som et språk hvor man kan teste ut og eksperimentere med alle mulige slags programmeringsmodeller.

På tide med litt kode

Nedenfor er et komplett Oz-program som skriver ut summen av alle tall fra 0 til 999 som er multipler av 3 eller 5. Det er ikke det korteste programmet jeg kunne ha skrevet, men illustrerer i stedet flere aspekter ved språket.

Oz har såvidt jeg vet ingen vanlige løkker. Det ble derfor naturlig å velge en funksjonell, stream-basert løsning.

I koden får du se hvordan man definerer funksjoner, inkludert en rekursiv funksjon som bygger opp en liste. Du får også se hvordan man bruker høyereordens-funksjoner, hvordan man sender en funksjon som et argument, og hvordan man deklarerer en funksjon in-line i et kallet til FoldL (“fold left”, funksjonen som summerer opp alle tallene).

10 functor
11 import
12    Application
13    System
14 
15 define
16 
17    %% recursive function to create a new list
18    fun {Range From To}
19      if From == To then [From]
20      else From | {Range From+1 To} end
21    end
22 
23    %% function to get value to include in sum
24    fun {Euler1Value X}
25      if X mod 3 == 0 then X
26      elseif X mod 5 == 0 then X
27      else 0 end
28    end
29 
30    %% Variables bound in definition body
31    Values
32    Sum
33  in
34    Values = {Map {Range 0 999} Euler1Value}
35    Sum = {FoldL Values
36                 fun {$ X Y} X + Y end
37                 0}
38    {System.showInfo Sum}
39    {Application.exit 0}
40 end

Du har sett meg bruke map og fold så mange ganger nå at dette bør være helt greit å skjønne. Når du ser noe slikt som {Foo Bar Zot}, så er det et funksjonskall. Foo er funksjonen, og Bar og Zot er argumentene.

Min opplevelse av Oz

Da jeg begyte å studere Oz virket det svært fremmed og nesten uforståelig. Dokumentasjonen var frustrerende; den var skrevet for å lære meg språket grundig, ikke for at jeg raskt skulle kunne komme igang.

Etter hvert begynte jeg derimot å se paralellene til Erlang – spesielt hvordan Erlang håndterer lister. Og da jeg så arven fra Lisp i språket begynte brikkene å falle på plass.

Nå tror jeg det skal gå ganske greit å fortsette med Oz. Det er egentlig et ganske enkelt språk, men med avanserte muligheter.

Hvordan komme i gang

Hovedimplementasjonen av Oz kalles the Mozart Programming System. Det er open source, og tilgjengelig på Unix, Linux, FreeBSD, Windows og Mac OS X.

Jeg lastet det ned på Windows, men fikk det ikke til å virke helt som tiltenkt – GNU Emacs, som er en del av det interaktive miljøet, ville ikke kjøre. Jeg endte til slutt opp med å programmere online i ideone, et kjekt sted hvor man kan kompilere og kjøre programmer i et utall ulike språk.

Mozart-sidene har også den mest komplette dokumentasjonen for Oz. I tillegg finnes det en bok som heter Concepts, Techniques, and Models of Computer Programming. Dette er en lærebok i programmering som bruker Oz til å illustrere alle de ulike aspektene og paradigmene. Sikkert ikke en dum bok å ønske seg til Jul.

GNU Octave

De fleste språkene jeg presenterer her på bloggen er såkalte “general purpose” språk som kan brukes til hva som helst. Men av og til kan det være greit å kjenne til språk som er skreddersydd for en spesifik oppgave; som for eksempel matematiske beregninger.

octave

Med et slikt verktøy kan man løse enkelte oppgaver mye raskere enn man kan i de “vanlige” språkene. De kan f.eks. egne seg godt til å prototype ulike algoritmer, og brukes blant annet til dette innenfor felt som maskinlæring.

Det finnes mange språk og verktøy å velge blant, men noen av de mest kjente er:

MATLAB (Matrix Laboratory) betegnes som et fjerdegenerasjons programmeringsspråk. I MATLAB kan man manipulere matriser, plotte funksjoner og data i flotte grafer, implementere algoritmer, lage brukergrensesnitt, og bruke moduler skrevet i andre språk som for ekssempel C++ eller Java. Språket brukes mye innenfor utdanning.

Mathematica er en programvare for matematiske beregninger (duh!). Det er mye brukt av vitenskapsfolk, ingeniører og matematikere. Mathematica inkluderer et programmeringsspråk som støtter både den funksjonelle og den objektorienterte paradigmen, har et hav av verktøy for visualisering, datamining, bildeprosessering, og mye annet rart, og koster skjorta og en halv arm!

R er et annet programmeringsspråk og miljø for å utføre statistisk analyse, og for å utvikle programvare for slik analyse. I motsetning til MATLAB og Mathematica er R gratis, og kildekoden er tilgjengelig.

Og så har du GNU Octave, det programmeringsspråket ment for numeriske beregninger som denne artikkelen egentlig handler om. Det er også gratis, og har blitt laget for å være kompatibelt med MATLAB; er man “litt forsiktig” når man koder skripts for Octave, så kan de fint kjøres på MATLAB også.

Euler-oppgaven løst i Octave

Denne oppgaven som jeg nå driver og implementerer i ulike språk egner seg selvsagt godt til å løses i GNU Octave. I skjermbildet nedenfor kan du se at jeg har laget et lite skript på fem, seks linjer. Jeg har så kjørt dette fra Octave’s kommandolinje, og programmet har skrevet ut svaret (markert med rød ring).

I tillegg har skriptet plottet hvordan summen vokser etterhvert som vi legger til tall opp mot 1000.

octave

Jeg lar bildet og koden tale for seg selv. Jeg er langt fra noen ekspert på verktøy som dette, og måtte “grave litt” i dokumentasjonen for å løse oppgaven.

Jeg skulle derimot ønsket at jeg kunne det bedre, og håper jeg får muligheten til å lære mer. For jeg havner rett som det er i situasjoner hvor jeg skulle ønske at jeg enkelt kunne analysere og visualisere en funksjon eller et datasett, men hvor jeg føler det blir litt for tungvindt med et vanlig programmeringsspråk.

Octave laster du ned fra gnu.org. Der finner du også en svær manual, en wiki med mange tutorials, og mye annet snacks.

Fantom

For cirka seks år siden dukket det opp et interessant språk som utviklerne kalte Fan. Det viste seg derimot å være vanskelig å google det navnet, og spåket endret derfor navn til Fantom i 2009. Fantom er en typisk smeltedigel av egenskaper man finner i andre språk, og er ment å være et praktisk verktøy. Det er objektorientert, støtter funksjonell programmering, og har actors – eller støtte for samtidighetsbasert programmering som Joe Armstrong ville ha sagt.

Fantom er fortsatt under aktiv utvikling og endring, men er likevel robust og er brukt i produksjon flere steder.

fantom

Fantom-kode har en Java/C#-lignende syntaks som bør være grei å forholde seg til for de aller fleste. Språket er statisk typet, men har også flere dynamiske features som type inference, implisitt casting, og en dynamic invoke-operator som lar deg kalle en hvilken som helst metode uten statisk kontroll.

Det finnes to ulike typer i Fantom: klasser og mixins. Klasser danner grunnlaget for objekter, og all data i Fantom er objekter, inkludert value types som Int og Bool. Akkurat som Java og C# har Fantom single inheritance, men mixins gir deg mulighet til å utvide objektene på måter Java/C# ikke kan (for eksempel sånn som jeg presenterte i posten om DCI arkitekturen i mars 2010).

Kan kjøre på ulike plattformer

Fantom er laget for å være portabelt, og kan kjøres på Java VM, på .NET CLR, og med JavaScript i en browser. Fantom kompileres til Fantom bytecode, og denne kompileres igjen ned til valgt platform. Per i dag er det Java-runtimen som er mest stabil, og .NET-implementasjonen er mer et proof-of-concept.

Hvordan ser koden ut?

Du begynnes sikkert å bli litt lei av denne oppgaven nå, men jeg skal altså løse Euler-problem nummer 1 i Fantom også. Koden nedenfor viser blant annet hvordan man definerer en klasse med en main-metode, og hvordan lambda-uttrykk ser ut i dette språket. Jeg har valgt en funksjonell, stream-basert løsning denne gangen med bruk av en range, filtrering og aggregering.

10 class Euler1
11 {
12   static Bool MultipleOf(Int n, Int[] dividents)
13   {
14     return dividents.reduce(false) |Bool result, d->Bool|
15     {
16       result.or(n % d == 0)
17     }
18   }
19 
20   static Void main()
21   {
22     echo((1..999)
23       .toList()
24       .findAll |n->Bool| { MultipleOf(n, [3, 5]) }
25       .reduce(0) |Int memo, n->Int| { memo + n } )
26   }
27 }

Måten jeg har implementert MultipleOf-metoden på er både overkill og lite lesbart. Men når du har løst den samme oppgaven fjørti ganger begynner du etterhvert å eksperimentere litt. :)

I linje 16 utnytter jeg det faktum at alt, også boolske verdier, er objekter i Fantom. Jeg kaller derfor metoden “or” for å kombinere to boolske uttrykk. Men frykt ikke, alle de vanlige operatorene du er vandt til, som && og ||, finnes også.

Samtidighet

Samtidighet er det området hvor Fantom skiller seg mest fra Java og C#. Mens Java og C# i bunn og grunn baserer seg på en modell med delt minne mellom tråder, hvor man må synkronisere tilgang til data med locks for å forsøke å unngå deadlocks og race conditions, så tillater ikke Fantom deling av data. Det vil si, Fantom tillater ikke deling av data som kan endres (mutable state).

I stedet har Fantom to alternative teknikker for samtidighetsprogrammering.

Det første er data som ikke kan endres – immutability. Det er dette som har gjort de funksjonelle språkene som f.eks. Clojure og Haskell populære. Ikke-muterende data er bygget inn i Fantom, og kan trygt og effektivt deles mellom tråder.

Den andre teknikken er message passing. Dette er det som har gitt språket Erlang sin fremgang de siste årene. Fantom har et actor API som er bygget på ideen om å sende meldinger mellom asynkrone arbeidere.

Jeg har implementert en løsning til på Euler-oppgaven for å illustrere hvordan man kan bruke actors. Jeg beklager at koden inneholder en del repetisjon, men jeg tror det får frem poenget mitt på en ok måte.

I løsningen nedenfor oppretter jeg fire actors. Den første (summer) tar imot vilkårlige tall, legger dem til en sum som den holder rede på, og returnerer summen. De tre øvrige deler på å finne alle tallene som skal være med i løsningen, og sender disse til summer.

Til slutt spinner jeg inntil de tre arbeiderne er ferdige, og så sender jeg en siste melding til summer for å få tilbake svaret.

10 using concurrent
11 
12 class Euler1
13 {
14   Void main()
15   {
16     pool := ActorPool()
17 
18     summer := Actor(pool) |Int change->Int|
19     {
20       sum := (Int)Actor.locals.get("sum", 0) + change
21       Actor.locals["sum"] = sum
22       return sum
23     }
24 
25     multiplesOf3Actor := Actor(pool) |msg|
26     {
27       for (n:=1; n<1000; ++n)
28         if (n % 3 == 0) summer.send(n)
29       echo(msg); return null
30     }
31 
32     multiplesOf5Actor := Actor(pool) |msg|
33     {
34       for (n:=1; n<1000; ++n)
35         if (n % 5 == 0) summer.send(n)
36       echo(msg); return null
37     }
38 
39     multiplesOf15Actor := Actor(pool) |msg|
40     {
41       for (n:=1; n<1000; ++n)
42         if (n % 15 == 0) summer.send(n * -1)
43       echo(msg); return null
44     }
45 
46     f1 := multiplesOf3Actor.send("All multiples of 3 added!")
47     f2 := multiplesOf5Actor.send("All multiples of 5 added!")
48     f3 := multiplesOf15Actor.send("All multiples of 15 removed!")
49     echo("Done sending startup messages")
50 
51     // Spin-Wait for work to finish
52     while(true)
53       if(f1.isDone.and(f2.isDone.and(f3.isDone)))
54         break
55 
56     echo("The answer is ${summer.send(0).get}")
57   }
58 }

Når jeg kjører koden ser det ut som dette:

C:\code>c:\fantom\bin\fan.exe euler1_with_actors.fan
Done sending startup messages
All multiples of 15 removed!
All multiples of 3 added!
All multiples of 5 added!
The answer is 233168

Her ser du at i dette tilfettet ble multiplesOf15Actor ferdig før multiplesOf3Actor. Det er selvfølgelig overkill å bruke fire tråder til å beregne summen av alle tall som er multipler av 3 eller 5 under 1000, men actor model er en veldig spennende måte å kode på for mange andre problemområder.

Hvordan komme igang

Fantom.org er språkets offisielle side, og her finner du alt du behøver for å komme igang. Under “Docs” finner du utførlige manualer, eksempelkode og full API-dokumentasjon.

Merk at selv om Fantom er et relativt ungt språk så finnes det allerede ganske god editor/IDE-støtte for språket. FantomIDE er bygget på Netbeans, F4 er et annet som baserer seg på Eclipse, og du får støtte for Fantom i TextMate, TextPad, Emacs, Vim og flere andre steder.

Fantom inkluderer også en interaktiv REPL (Fansh), innebygget funksjonalitet for automatisert enhetstesting (Fant), og en egen build-motor som baserer seg på buildscripts skrevet i Fantom. Det har blitt lagt ned mye bra arbeid i dette språket, og det blir spennende å se hvordan det utvikler seg videre.

Nemerle

Nå skal du få møte det jeg oppfatter som det aller mest spennende språket på .NET-plattformen for tiden. Nemerle er som en krysning mellom C# og F#, med Lisp-lignende makro-støtte som en ekstra bonus. Her har du et veldig kraftig verktøy hvor du kan programmere imperative-, objektorienterte- og funksjons-baserte løsninger proppfulle av meta-features. Eller som hjemmesiden sier, et <<Programming language for “special forces” of developers>>.

nemerle

Versjon 1.0.0 ble lansert i mai i år, men arbeidet med språket startet så langt tilbake som i 2003. Programmeringsspråk skapes ofte av én person, enten som noe han gjør privat eller med backing av et firma som f.eks. tidligere Sun eller Microsoft. Andre ganger står det en kommité bak, men det resulterer sjelden i noe bra. Nemerle derimot er skapt av en gruppe utviklere ved University of Wroclaw i Polen, og deres innsats er imponerende.

(At flagget på roboten ble russisk var en glipp.., sorry! Det skulle selvsagt vært det polske.)

Nemerle er sterkt typet, og har kraftig type inference. Utviklere med bakgrunn fra språk som Java eller C# vil kunne kjenne seg igjen, men språket har også mange egenskaper hentet fra funksjonell programmering som tail call optimization, pattern matching, algebraiske datatyper, partial application, tupler osv.

Du finner også såkalte Computation expressions, som så langt jeg har forstått er det samme som monader.

Videre støtter Nemerle streng-interpolering, noe som ikke er vanlig i statisk typede språk. Det har støtte for LINQ, og du kan benytte deg av aspect-oriented programming (AOP). Dessuten har det XML literals, noe du også finner i språk som Scala og Visual Basic .NET.

Generelt sett er språket proppfullt av features, og det virker som om de er satt sammen på en meget behagelig måte. For å vise at Nemerle er et allsidig språk har jeg laget fire løsninger på Euler-oppgaven

En imperativ løsning

La oss først se hvordan et Nemerle-program ser ut, og om vi kan gjøre “vanlig”, imperativ programmering i dette språket.

Nemerle-program består av klasser og/eller moduler (moduler er som statiske klasser). Et program må ha en Main-metode for å kunne kjøres. Merk at using-statements (import av navnerom) er utelatt fra eksemplene.

10 module Program
11 {
12     Main() : void
13     {
14         mutable sum = 0;
15 
16         for (mutable n = 1; n < 1000; n++)
17             when (n % 3 == 0 || n % 5 == 0)
18                 sum += n;
19 
20         WriteLine(sum);
21     }
22 }

I dette eksempelet opprettet jeg en sum-variabel som det er lov å endre (mutable). Nemerle finner selv ut at dette er en integer. Så kjører jeg en for-løkke, gjør en test, og legger tallet til sum om testen var positiv. Ganske rett frem dette her.

Jeg brukte “when” til testen, fordi “if” krever en else-blokk. Det er vanlig med påkrevd else i funksjonelle språk – Clojure er et eksempel på et språk som har det samme skillet.

Range, filter og fold med Labdas

Men la oss glemme for-løkken.., den er gammeldags! Her følger en såkalt stream-basert løsning hvor jeg oppretter en range, filtrerer den, og til slutt aggregerer summen med FoldLeft.

23 module Program
24 {
25     Main() : void
26     {
27         def numbers =
28             NList.Filter ($[1..999], fun (n) { n % 3 == 0 || n % 5 == 0 });
29 
30         def result = NList.FoldLeft (numbers, 0, fun (n, acc) { acc + n });
31 
32         WriteLine(result);
33     }
34 }

Dette illustrerer først og fremst hvordan lambda-uttrykkene ser ut i Nemerle. Ellers har du jo sett denne løsningen ganske mange ganger nå.

Nøstede funksjoner og pattern matching

En ting Nemerle skiller seg litt fra endel andre språk på er muligheten til å definere funksjoner inne i andre funksjoner. I den følgende løsningen har jeg opprettet to funksjoner inne i Main-metoden. Disse bruker pattern matching og rekusjon til å finne summen – en teknikk du også så meg bruke i F#.

35 module Program
36 {
37     Main() : void
38     {
39         def include(n)
40         {
41             n % 3 == 0 || n % 5 == 0
42         }
43         def euler1(n, sum)
44         {
45             | (1000, _)              => sum
46             | (_, _) when include(n) => euler1(n+1, sum+n)
47             | (_, _)                 => euler1(n+1, sum)
48         }
49         WriteLine(euler1(0, 0));
50     }
51 }

List comprehension

Den enkleste løsningen har jeg likevel spart til slutt. Nemerle har støtte for list comprehensions, som er et kraftig verktøy for å opprette filtrerte serier. Jeg kan dermed skrive ut svaret med en ganske leselig one-liner.

52 module Program
53 {
54     Main() : void
55     {
56         WriteLine($[x | x in [1..999], x % 3 == 0 || x % 5 == 0].Sum());
57     }
58 }

Hvorfor bruke tid på Nemerle

Nemerle er et praktisk og godt verktøy som lar deg kombinere objektorientering og funksjonell programmering. I tilleg har du makroene som lar deg utvide syntaksen og kompilatoren ganske enkelt. Nemerle vil derfor egne seg svært godt til å redusere mengden “boilerplate” i større løsninger, og til å lage interne DSL’er.

Sammenlignet med F# er Nemerle trolig enklere å forstå og å komme igang med for programmerere som ikke har vært eksponert for ML-lignende språk tidligere. Nemerle’s minner nemlig mer om C# gjennom bruk av krøllparanteser, klasser og andre syntaks-elementer. Man kan begynne med objekter om man er vandt til det, og gradvis ta i bruk de andre egenskapene etterhvert som man lærer.

Hvordan komme igang

Nemerle er støttet gjennom en extension i Visual Studio 2008. 2010-støtten er i beta, men fungerte greit nok for meg. Man får farger, IntelliSense, designtime hints og sikkert andre features jeg ikke har oppdaget. Du finner også støtte for Nemerle til SharpDevelop (om du er på Linux, eller foretrekker open source).

Jeg tror det vil være svært enkelt for et team med C#-utviklere å konvertere til å bruke Nemerle. Man kan selvfølgelig bruke språket på enkeltdeler; .NET-løsninger kan fint blande prosjekter skrevet i ulike språk. Men med Nemerle kan man i tillegg inkludere C#-kode i Nemerle-prosjekter – noe lignende har jeg aldri sett før.

Dessuten tilbyr Nemerle-teamet en C#-til-Nemerle converter. Hva med å kjøre den på din eksisterende kodebase, og se hva som kommer ut i andre enden?

Du finner Nemerle på nemerle.org. Språket har også en brukbar wiki med ganske mye informasjon, linker til API-dokumentasjon og tutorials.

Som sagt synes jeg Nemerle er et veldig spennende språk, og jeg anbefaler deg å ta det i nærmere ettersyn!

Unlambda

“The effect of reading an Unlambda program is like having your brains smashed out by a Lisp sexp wrapped around an ENIAC. You won’t find anything like it west of Alpha Centauri.” – The Hitch-Hacker’s Guide to Programming

unlambda

Unlambda beskrives som et mareritt som har blitt virkelig. Det er med vilje designet for å gjøre programmeringen vanskelig og smertefull – eller utfordrende og underholdende, om du lærer deg å like denslags. Å skrive Unlambda-kode er vanskelig, men å lese Unlamdba-kode er praktisk talt umulig!

Det dreier seg her om et funksjonelt programmeringsspråk ala Scheme. I slike språk utgjør funksjonen den viktigste byggestenen, og i Unlambda er funksjonen faktisk det eneste man har å jobbe med. Matematisk kan man si at kjærnen i Unlambda er en implementasjon av Lambda Calculus, men uten selve Lambda-operatoren.

Unlambda er altså ikke ment å være et praktisk anvendelig språk. I stedet demonstrerer det svært ren, funksjonell programmering. Man kan ikke ha variabler, og har ingen vanlige operatorer eller datatyper. Alt man har er noen få innebygde funksjoner som hver tar én annen funksjon som parameter, og returnerer en ny funksjon. For å gjøre det ekstra kryptisk (og elegant) består hver funksjon av kun et tegn. Språket har ingen syntaks utover dette.

Hvorfor skal man bruke tid på Unlambda?

Det som skremmer meg med Unlambda er at det er et språk jeg sålangt ikke klarer å forstå. Jeg tror derimot at om man jobber litt med det, og begynner å skjønne hvordan man bruker det, så har man forstått noe svært sentralt innen funksjonell programmering. Man vil sansynligvis stå bedre rustet til å utføre små mirakler i Haskell, i Lisp-dialektene eller tilsvarende språk.

Har du først og fremst en praktisk tilnærming til programmering er altså dette språket sansynligvis ikke noe for deg. Men om du liker en utfordring, og har tro på at all kunnskap kan berike deg, så er Unlambda noe av det mest spesielle du kan lære.

Hvordan ser det ut?

Jeg beklager, men jeg har ikke klart å lage et program som løser Euler-oppgave 1. Men jeg tviler på at det har noe nå si. Følgende “lånte” Unlamda-program kalkulerer og skriver i stedet ut Fibonacci-tall i form av linjer med stjerner.

1 ```s``s``sii`ki
2   `k.*``s``s`ks
3  ``s`k`s`ks``s``s`ks``s`k`s`kr``s`k`sikk
4   `k``s`ksk

Som du ser er det mest brukte tegnet i dette programmet “backquote”. Dette er rett og slett Unlambdas apply-funksjon. S står for substitution, k kalles constant generator, og i er identity-funksjonen som bare returnerer sitt argument uendret. R skriver ut en ny linje, og .* skriver ut en stjerne.

Her ser du hvordan det ser ut når jeg kjører det med Java-implementasjonen av Unlambda (den fortsetter å kjøre i det uendelige antar jeg, men jeg trykket Ctrl-C for å stoppe den):

C:\unlambda-2.0.0\java>java unlambda.Execute fib.unl

*
*
**
***
*****
********
*************
*********************
**********************************
*******************************************************

Tar du utfordringen?

Siden jeg feiget ut og ikke klarte å løse den vanlige adventsoppgaven, så har vi jo egentlig en utfordring her. Kjempekudos til førstemann som poster løsningen i en kommentar!

hvordan kommer man i gang?

Det første man må gjøre er å lese det som står på den ofisielle websiden til The Unlambda Programming Language. Deretter kan man laste ned Unlambda versjon 2, som inkluderer implementasjoner i C, Java, Perl, Scheme med flere, samt eksempel-programmer og noen verktøy for Unlambda-utviklere. Og så er det bare å klø seg i hodet og forsøke å få ting til å virke :-)


Torbjørn: La oss anta to ulike definisjoner av Template Method pattern - de to ytterpunkte...

Lars-Petter: Hei igjen. Siden du inviterer til å ta diskusjonen i bloggen, og har tatt deg t...

Torbjørn: Lars-Petter: Det er én måte å se det på. Det er absolutt fortsatt Template M...

Lars-Petter: Hei. Har du ikke i prinsippet her gått over fra Template Method (arv) til Strat...

Christian Abildsø: I alle fall i C#, så føles dette som kode som blir mer fleksibel men vanskelig...

Torbjørn: Hei Henrik, og takk for tilbudet. Ble oppmerksom på Rasberry Pi for under en uk...

Henrik Sandaker Palm: Ang. større hobby prosjekt. Du er som er en slik rakker på programmering har j...

Øivind Nilsen: Slutt å bruke mobilnummeret mitt som eksempel !...

Bjørn Einar Bjartnes: Jeg har også latt meg fascinere av Clojure, uten at jeg har kommet så veldig l...

Bjørn Einar Bjartnes: Sweet :) Jeg tror egentlig jeg liker det som det er, med musikk. Litt av utford...

 Hold deg oppdatert

Søk i bloggen

Ferske innlegg

  • Template Method del 4: Multippel arv
  • Template Method Intermesso
  • Template Method del 3: Bare funksjoner
  • Template Method del 2: På vei mot funksjonell programmering
  • Kategorier

  • .net ninja (37)
  • Bøker (17)
  • Diverse prosjekter (35)
  • DSL (10)
  • Erlang (10)
  • F# (5)
  • Hardware (1)
  • Jobb (77)
  • Julekalender (51)
  • kjempekjekt.com (23)
  • LISP/Clojure (33)
  • NNUG / community (60)
  • O/RM & databaser (10)
  • Off topic (116)
  • OO-design/clean code (30)
  • Podcasts (14)
  • Polyglot (77)
  • Ruby (27)
  • Silverlight / RIA (3)
  • Software/verktøy (20)
  • Softwareutvikling (20)
  • Testing / TDD (30)
  • the contiki strip (13)
  • User experience (3)
  • WCF (3)
  • Webutvikling (32)
  • WPF (9)
  • WTF (12)
  • Last ned Wallpaper

    Programmeringsbloggens tøffe skrivebordsbakgrunn med snippets fra ulike språk laster du ned her!

    Abonner via epost

    Om du vil kan du få alle nye blogposter tilsendt til din epost. Abonner nå, det er kjempeenkelt!

    Meta