Factor


mandag 19. desember 2011 Julekalender Polyglot Factor

Forth var et spennende og anderledes språk – men det er forferdelig gammelt, og virker ikke spesielt praktisk til større og mer komplekse oppgaver. Factor er den moderne arvtageren til Forth; et stack-basert programmeringsspråk med et rikt biblotek, ulike datatyper og til og med objekter, makroer, databasedrivere, et GUI-rammeverk, og med mulighet for å kommunisere med programmer skrevet i C, Objective-C og Fortran.

Forth var en søt liten filosof som kunne lære deg noe grunnleggende om problemløsning. Factor er en orntlig kraftkar som kan løse de utfordringene du har i den virkelige verden!

Factor

Utviklingsmiljøet

Factor er på samme måte som Smalltalk et image-basert språk og utviklingsmiljø. Når man starter det opp får man et vindu hvor man interaktivt kan skrive kode, inspisere datastacken, osv. Miljøet har ulike måter å hjelpe utvikleren, og inkluderer blant annet en hyperlink-basert browser hvor man kan studere biblotekene man har til rådighet, og lære Factor gjennom ulike tutorials.

I skjermbildet nedenfor ser du hovedvinduet til venstre, hvor jeg har laget en ny definisjon og testet den. Vinduet jeg har åpnet til høyre er hjelpe-browseren.

Factor_env

Jeg ble ganske imponert av miljøet egentlig. Det er noe helt annet enn IDE'ene jeg er vandt til, men virker perfekt for oppgaven.

Litt kode

Nå skal vi løse oppgaven vår igjen: finne summen av alle multipler av 3 eller 5 som er mindre enn 1000. Som du vil se ligner definisjonene i struktur svært på de du så i artikkelen om Forth.

10 USING: math kernel sequences math.ranges prettyprint ;
11 IN: euler1
12 
13 : mult? ( x y -- ? ) rem 0 = ;
14 
15 : mult3? ( x -- ? ) 3 mult? ;
16 : mult5? ( x -- ? ) 5 mult? ;
17 
18 : mult3or5? ( x -- ? ) dup mult3? swap mult5? or ;
19 
20 : sumMultsOf3or5 ( seq -- n ) [ mult3or5? ] filter sum ;
21 
22 : solveEuler1 ( -- ) 0 1000 (a,b) sumMultsOf3or5 . ;

Hovedforskjellen fra løsningen i Forth er at jeg her har tilgjengelig en funksjon som oppretter en range for meg på stacken, en annen funksjon som filtrerer, og til slutt en funksjon som summerer hele stacken. Factor har altså et rikere biblotek med kraftigere definisjoner og rikere datatyper enn det Forth har.

Det du ser i parantes mellom definisjonsnavnet og selve implementasjonen er dokumentasjon av hvilke effekter definisjonen vil ha på datastacken. ( x y – ? ) betyr at mult? forventer to elementer på stacken, at disse vil bli "poppet" bort, og at et nytt, boolsk element vil bli pushet tilbake. Du kan godt velge å se på det som en funksjonssignatur, som spesifiserer inn-parametre og ut-parametre.

Koden forklart i detalj

I figurene nedenfor har jeg forsøkt å illustrere hvordan enkelte av ordene jeg har opprettet gjør jobben sin på stacken..

factor1

Over ser du hvordan man kan bruke mult? til å finne ut om 8 er et multippel av 5. Da må 8 og 5 først være på stacken. Rem-kommandoen vil poppe begge tallene, og pushe resten etter divisjon – altså 3 - tilbake på stacken. Deretter pusher vi 0, og så = (erlik-kommandoen), som igjen popper to tall og pusher svaret, som i dette tilfellet er False: 8 er ikke et multippel av 5.

factor2

Over ser du den litt mer kompliserte mult3or5?, som sjekker ett tall som ligger øverst på stacken – i dette tilfellet 20. Først dupliseres det, fordi jeg trenger å teste det to ganger. Deretter kalles mult3?, som spiser ett tall, og pusher om det var et multippel av 3 eller ikke. Så må jeg kjøre swap for å få det andre 20-tallet på toppen, før jeg kaller mult5?.

Til slutt bruker jeg or-kommandoen til å avgjøre om ett av de to øverste elementene er True. Resultatet blir liggende igjen på stacken.

factor3

Til slutt ser du hvordan sumMultsOf3or5 gjør jobben sin (figuren lyver litt, en sekvens ligger faktisk bare som ett element på stacken, men jeg tror ikke det spiller noen rolle for deg akkurat nå).

Input på stacken er altså en sekvens med tall. Deretter pushes det en kodeblokk som inneholder et kall til mult3or5?. Når filter så blir kalt vil den poppe første element (blokken) og kalle den for hvert element i sekvensen. Hvis blokken returnerer True vil tallet bli beholdt. Til slutt kalles sum, som summerer sekvensen, og vi står tilbake med svaret på stacken.

Hvordan komme igang

Factor finner du på factorcode.org. Last det ned for din plattform, og sett igang. På concatenative.org-wikien finner du en rekke tips til hvordan du begynner å lære språket.

Og så var det bare fem dager igjen til Jul. Lykke til!


comments powered by Disqus