« mars 2007 | Main | juli 2007 »

april 26, 2007

Programspråket Groovy: Tre år senare

För mer än tre år sedan skrevs om det då sprillans nya programspråket Groovy. Det har hänt en hel del sedan dess, men först lite mer om Groovy.


Groovy är ett "agilt" programspråk likt Ruby, JRuby, Python, Jython, Perl etc, dvs det som numera inte så ofta kallas för "script-språk" och som man ibland kallar för VHLL (Very High Level Language). Det finns alltså många högnivåkonstruktioner i dessa språk och man kan köra program utan att behöva kompilera till exekverbar kod (eller bytekod). Liksom JRuby och Jython inriktar Groovy sig på Java-världen och använder sig av Java .class-filer och kan även generera bytecode.

På sajten sin presenterar man sig så här:

[Groovy] is an agile dynamic language for the Java Platform with many features that are inspired by languages like Python, Ruby and Smalltalk, making modern programming features available to Java developers with almost-zero learning curve

eller - för att citera boken Groovy in Action (se ref. nedan) - “Java-stylish with a Ruby-esque feeling”.


Det har hänt en hel del sedan jag först stötte på språket. Framför allt var det två saker som gjorde att jag tog upp intresset igen för några veckor sedan:
* det har blivit så stabilt så att version 1.0 skeppades i januari, och man håller just nu på med att förbereda releasen 1.1 (lagom till JavaOne)
* det har kommit ett par böcker om språket, varav den ena "Groovy in Action" har lästs och beskrivs mer nedan.

Och i går vann man första pris på JAX 2007 ("the most important Java conference in Germany"): Groovy wins first prize at JAX 2007 innovation award. Kul!

Findings eller Saker som är skoj med Groovy
Jag tänker här inte skriva någon introduktionskurs kring Groovy. Sådant finns på/via sajten eller annorstädes. I stället kommer här några disparata findings om saker är trevligt/speciellt i språket samt några gotchas. Exemplen råkar vara mycket med text och tal eftersom det ju är sådant som jag sitter med här hemma...


För att undanröja framtida kommentarer: Ja, jag vet att mycket (eller allt) som beskrivs här är möjligt att göra i andra programspråk, speciellt i de agila kusinerna. Frågan är inte så mycket att utan snarare hur (se nedan om syntaktiskt socker). För tillfället ligger Groovy mycket högt på min lista över språk som känns bra att skriva, även om jag egentligen inte tillhör den direkta målgruppen ("Javautvecklare som vill blir effektivare" som man uttrycker det i reklamen).


Synkaktiskt socker eller En liten skillnad gör många tangentnedtrycksbesparingar
Eftersom jag hävdar (utan att argumentera) att "syntaktiskt socker i ett programspråk är allt" passar det bra med ett litet exempel: Följande lilla skillnad mellan Ruby och Groovy gör att Groovy känns bättre, nämligen hur man skriver closurevariabeln. Med ett svenskt tangentbord är det meckigare att trycka Alt-Gr-"|" + x + Alt-Gr-"|" än "-" + ">" + "x" samt att skriva "#{}" än "$". Efter några år har man sparat förfärligt många tangenttryckningar med Groovys variant...

Ruby:

(1..10).each{ | x | print "#{x}" }

Groovy:

(1..10).each{ x -> print "$x " }

(1..10).each{ print it }

Det andra Groovy-exemplet visar att det finns en magisk variabel it som man kan använda direkt så man slipper deklarera någon temporär variabel. Fler tangenter som slits mindre. (Ruby har haft en sådan variabel $_ men det är tyvärr deprekerad sedan ett tag. Jepp, jag tycker att Perl är ett mycket trevligt språk.)

Å andra sidan: om det viktigaste är att spara tangenttryckningar bör man titta på programspråket J.

Lite avstickare: önskefeatures i ett programspråk
Ovanstående ska ses som ett exempel på vad jag tycker är trevligt med både Ruby och Groovy, nämligen att allt är objekt och att det finns någon form av stöd för funktionsprogrammering (ju mer stöd desto bättre).

Båda språken uppfyller många av mina önskefeatures för programspråk:

* fullständigt objektorienterat med "öppna klasser". Groovy har inte helt öppet som Ruby, men det går att öppna upp med vissa handgrepp. Se nedan.

* direkt stöd för hashtabeller i språket, dvs literaler: {"x"=> 1, "y"=>2} och vektorer: [1,2,3,4]. Gärna också intervall: (1..10)

* stöd för reguljära uttryck direkt i språket ("=~" som ju Perl och Ruby också har)

* stöd för funktions(liknande)programmering med syntaktiskt tilltalande sätt att arbeta med dem. Exempelvis: closures och möjlighet till obegränsad kedjning (chaining). (Chaining ett mycket trevlig programmeringsparadigm. Att jag tycker om både chaining och Unix-filosofin med att pipa text mellan program är definitivt ingen slump. Snarare tvärtom.)

* automatiskt stöd för arbiträr precision så att man kan göra roliga matematiska experiment. I Groovy måste man i och för sig ange "G" i slutet på ett tal om det ska räknas arbiträrt. Man kan göra saker som

(2..10).each{mod->(1..100).findAll{it % mod ==0}.inject(1G){x,y -> y*=x}.each{ println it} }

för att summera tal som är jämt delbara med ett visst tal. Notera att det krävs "1G". (Att jag inte vill se sådan kod i driftade program är en annan sak.)

* snabb loop över filer. I Groovy finns det syntaktiska sockret men är tyvärr lite långsamt. Se mer nedan.

* list comprehension som Haskell (och Python). Saknas tyvärr i Groovy (samt i Ruby och Perl)

Allt är objekt
En sak som jag brukar testa i ett nya programspråk som hävdar att "allt är objekt" är följande oerhört fåniga exempel. Notera att man måste använda en så kallad category (eller så kan man använda MetaClass men det känns inte så rent) för att öppna upp existerande klasser, i detta fall Number (i Ruby är det ju bara att öppna upp klassen).


class HakankCategory {
static def hakank(Object self) {
return "hakank väljer $self"
}

static def hakank(Object self, Number number) {
return "hakank väljer $self och $number"
}
}

use(HakankCategory) {
println 1.hakank()
println 1.hakank(2)
}

Kör man programmet (groovy program.groovy kommer följande:


hakank väljer 1
hakank väljer 1 och 2


Man kan här notera att Groovy stödjer "strikt typning" men det är inte nödvändigt att deklarera variabler med typer.

Direkt stöd för Java
Till skillnad från JRuby och Jython använder man i Groovy Java-liknande syntax för att anropa existerande Java-klasser. Ja, hela syntaxen i Groovy är mycket Java-liknande (förutom några saker såsom "def" för att definiera en variabel).

T.ex. följande lilla exempel använder det numeriska paketet Colt ("a set of Open Source Libraries for High Performance Scientific and Technical Computing in Java"):

import cern.jet.math.Artihmetic.*

cc = (0..10).collect{[it, cern.jet.math.Arithmetic.binomial(10,it)]}
println "cc: $cc"
println cc.collect{ it[1]}.sum()


Om man redan inte har colt*.jar-filerna i sin CLASSPATH är det bara att lägga in dem i katalogen ~/.groovy/lib så fixar Groovy resten. Sådant är trevligt.

CLASSPATH
Apropå CLASSPATH. Om det blir problem att köra programmen är det lämpligt att rensa CLASSPATH fulltständigt så att det inte blir konflikter med de versioner av paketen som följer med Groovy (t.ex. ant*.jar och antlr*.jar). Själva har jag rensat CLASSPATH direkt i samtliga program:

groovy
groovysh
groocyc
java2groovy

Filhantering
Naturligtvis finns det även agilt stöd för filhantering i Groovy. Nedanstående exempel visar även att man kan använda programmet direkt från kommandoraden för att lista filer som finns i den aktuella katalogen

groovy -e "new File('.').eachFileRecurse { println it }"


Ett annat exempel som jag använder för att testa filhantering i nya programspråk är hur snabbt det är att läsa och betarbeta filer, framför allt med reguljära uttryck. Följande har råkat bli en standardtest:


println new File("/usr/dict/words").grep(~/.*a.*b.*.c.*d.*e.*/).join("\n")

som läser ordlistan "/usr/dict/words" (standard på Linux-system) och listar de ord som någonstans innehåller alfabetets första fem bokstäver i ordning, med eller utan andra bokstäver emellan.


Just detta är en sak som gjorde mig lite besviken eftersom filhanteringen tog ungefär två gånger lång tid som motsvarande program för Ruby, Python och Perl. Förhoppningsvis är det något som kommer att fixa sig i framtida versioner. Utvecklingsversionen (blivande 1.1) skiljer sig inte nämnvärt i detta hänseende.

Builders
En annan trevlig sak är de s.k. builders, dvs stöd för att skapa olika typer av strukturer.

Ett exempel: För att skapa en (enkel) XML-fil skriver man ungefär så här (eller snarare exakt så om man liksom jag snor rakt av från sidan 235 i Groovy in Action). Man blandar alltså tag-namnen med full exekverbar kod. Notera att man inte behöver fördeklarera tag-namnen ("description", "number", "factor") utan det listas ut av buildern.


builder = new groovy.xml.MarkupBuilder()
builder.numbers {
description 'Squares and factors of 10..15'
for (i in 10..15) {
number (value: i, square: i*i) {
for (j in 2.. if (i % j == 0) {
factor (value: j)
}
}
}
}
}

resultatet blir:


<numbers>
<description>Squares and factors of 10..15</description>
<number square='100' value='10'>
<factor value='2' />
<factor value='5' />
</number>
<number square='121' value='11' />
<number square='144' value='12'>
<factor value='2' />
<factor value='3' />
<factor value='4' />
<factor value='6' />
</number>
<number square='169' value='13' />
<number square='196' value='14'>
<factor value='2' />
<factor value='7' />
</number>
<number square='225' value='15'>
<factor value='3' />
<factor value='5' />
</number>

GPath
GPath är ett XPath-inspirerat sätt att navigera sig genom datastrukturer (t.ex. XML-kod).

Ett enkelt exempel där man ska tänka sig att navigera en fet XML-fil (här som en textsträng):

def text = """
<characters>
<props>
<prop>dd</prop>
</props>
<character id="1" name="Wallace">
<likes point="2">cheese</likes>
</character>
<character id="2" name="Gromit">
<likes point="10">sleep</likes>
</character>
</characters>
"""

def node = new XmlSlurper().parseText(text);
println "\n" + node.children().size()
// Vad tycker Gromit om?
println node.character.find { it['@name'] == 'Gromit' }.likes.text()

Resultatet blir inte helt förvånande

3
sleep

Skalet groovysh
Ett agilt programspråk utan skal är otänkbart (eller i alla fall ofullständigt). T.ex. irb för Ruby, ipython för Python och perl -de 1 (eller zoid) för Perl. Så det finns naturligtvis ett sådant även för Groovy. Tyvärr är det väldigt rudimentärt, men det kommer att utvecklare mer senare.

Några saker att tänka på:

1. En egenhet är att man måste skriva "go" + Enter för att exekvera koden. Tanken är att man ska kunna skriva t.ex. en hel klassdefinition utan att störa parsern.

2. Det finns ingen history, inga redigeringsmöjligheter eller tabb-komplettering/"automatintrospektion" (dvs att som i irb/ipython skriva en variabel + TAB för att se metoder etc). De två första avhjälps enklast genom att använda en readline-wrapper såsom rlwrap. När det gäller introspektionen får man skriva så här

groovy> x = "kalle har en häst"
groovy> go

===> kalle har en häst

groovy> x.class.methods.name.sort()
groovy> go
...


3. Man bör vara försiktig med att deklarera variabler med def eftersom de är lokala variabler i det aktuella "go-blocket" och kan inte nås senare. Om man skippar def så går det bra.


Stöd för systemanrop
En annan vanlig här hemma är att anropa andra program, framförallt Unix-utiliteter såsom find, ls, wget, lynx etc. En del av funktionaliteten finns inbyggt i Groovy eller i Javas standardbibliotek som lätt kan anropas, såsom ovanstående exemplet med Dir, men där finns ju inte alla optioner man vill utnyttja.

Standardstödet för systemanrop i Groovy är i stort sett Javas exec, vilket inte räcker till. Det finns dock ett extra-paket Process (Groosh) som gör livet enklare för sådan hantering. T.ex. för att anropa programmet find för att lista .java-filer (notera att metoden findfinns inte definierad i Groosh utan "dispatchas" magiskt till ett systemanrop):


def gsh = new com.baulsupp.groovy.groosh.Groosh();
println (gsh.find(".", "-name", "*.java").toStringOut())

Här kan också nämnas en gotcha. Eftersom grep är en existerande metod i Groovy blir det namnkonflikt om man försöker anropa programmet via Groosh (kanske löses sådant i en senare version av Groosh?). Lösningen är att göra en enkel wrapper för grep (kallad grepwrapper)

#!/bin/sh

grep $*

Varför följande kan skrivas för att visa rader med strängen Gina (förkortningen för Groovy In Action)

gsh.grepwrapper("Gina", "*.groovy").toStdOut()


En aside om "dispatchern". Samma funktionalitet (i alla fall vad gäller själva anropsdelen av kommandot) kan enkelt göras i Ruby med hjälp av metoden missing_methods tack vare Rubys inbyggda stöd för systemanrop:

# Ruby-kod
class Missing
def method_missing(name, *args)
name_s = name.to_s
args_s = args.join(" ")
puts "Running #{name_s} #{args_s}:"
if (name_s =~ /rm/)
"Please don't do that: #{name_s}"
else
`#{name_s} #{args_s}` # det kan vara svårt att se att det är backticks här
end
end
end

m = Missing.new
puts m.ls("-lat *.groovy")
puts ""
puts m.du "-h"
puts ""
puts m.df
puts ""
puts m.rm
puts ""


I Perl används naturligtvis AUTOLOAD för samma funktionalitet:

# Perl-kod
sub AUTOLOAD {
my $program = our $AUTOLOAD;
$program =~ s/.*:://; # trim package name
system($program, @_);
}

date();
who('am', 'i');
ls('-l'); # man kan dock inte använda globs här, dvs *.pl
echo("Abadugabudabuda...");


Slut på asiden.


Annat skoj
* Integrerat stöd för Ant, dvs där man kan skriva Antanrop i Groovy-program: Groovy Ant Task
* Safe navigation, för att slippa kontrollera mot null hela tiden.
* GSQL ett högnivå-wrapper kring databasanrop.
* Olika stöd för testning: Testing Guide såsom JUnit-liknande modul, GroovyMocks etc.

Grails
Det går inte att komma undan utan att åtminstone nämna Grails (Groovy on Rails), ett Ruby On Rails-liknande ramverk. Det var synnerligen enkelt att få igång det efter instruktionerna men jag har inte gjort så mycket mer med det sedan.

Böcker
Det finns några böcker skrivna om språket eller relaterat.

* Groovy in Action (ISBN: 1932394842, ISBN13: 9781932394849, se även förlagets sida). Detta är Groovy-bibeln och som jag har läst med andakt. Det slår igenom (nästan alltid på ett positivt sätt) att författarna, som tillhör Groovys innersta krets, är stolta över sitt språk.

Det förutsättes i princip att läsaren är systemutvecklare så man går rätt snabbt djupt ner i "the goory details" och jämföra med Java, men även med andra agila programspråk. Speciellt intressant är kapitllen om closures, om de speciella "builders" som finns med i programpaketet samt diskussionerna varför de designat språket som de gjort.

(Jag hoppas nu att de gör en "Pickaxe" och lägger upp boken fritt tillgänglig på nätet, dvs som Ruby-gänget gjorde med första upplagan av Programming Ruby.)


* Groovy Programming - An Introduction for Java Developers (ISBN: 0123725070, ISBN13: 9780123725073) som jag inte läst. Det verkar dock vara en mer introducerande bok där man inte går in på djupet så mycket som "Groovy in Action". Men som sagt, jag har inte läst den. Se vidare bokens hemsida. Intressant nog finns där ett paket för funktionsprogrammering (i zipfilen GroovyBook). Jag var dock tvungen att kompilera om jar-filen (src/fp/fp.jar) för att det skulle fungera.


* om Grails: The Definitive Guide to Grails (ISBN: 1590597583, ISBN13: 9781590597583). Har inte läst den men den rekommenderas av andra.


* Det är åtminstone ännu en bok på gång: Groovy Recipes - Greasing the Wheels of Java (ISBN: 0978739299, ISBN13: 9780978739294), beräknad leveranstid slutet på augusti 2007. På beskrivningen verkar detta vara en kokbok.

Se även
Groovys metoder: GDK (Groovy JDK)

PDF av hela online-dokumentationen på groovy.codehouse (stor fel PDF-fil på nästan 600 sidor).

Mailinglistor:
groovy.user
groovy.dev
(Tyvärr har man tagit bort den rena textvarianten av arkivet.)


aboutGroovy
Samlingsbloggen Groovyblogs
Sven Haiges blog som bl.a. innehåller Groovy/Grails podcasts.

Groovys projektledare Guillaume Laforge har en bra föreläsning om Groovy i Simplifying Enterprise Development with Groovy. Föreläsningen var förra året innan man hunnit fixat allting till version 1.0 så vissa av exemplen visar viss förlegad kod som inte är fullt körbar. Men principen framgår tydligt.


Groovy User Guide.


Utvecklingsversionen finns här (subversionsrespositorium).

PLEAC - Groovy. PLEAC - (Programming Language Examples Alike Cookbook) har utgått från Perl Cookbook och visar hur andra programspråk löser samma problem ("lagar samma maträtter"). Intressant nog är Groovy det första programspråk som blev klar till 100% (förutom Perl då). Emellanåt visas en princip som är viktig (men som i och för sig kan upplevas som fusk i sammanhanget): Om det inte finns direkt stöd för en sak i Groovy använder en existerande Java-klass i Java (direkt i Javadistributionen eller Open Source).

En Sudoku solver in Groovy för er som kommer ihåg det glada 2006. :-)


För den som är intresserad av olika programspråk rekommenderas Programming Language News.

Posted by hakank at 10:20 EM Posted to Systemutveckling | Comments (1)

april 17, 2007

Blogg: ctail.avadeaux.net

ctail.avadeaux.net är en relativt (typ en månad) ny blogg som skrivs av en mycket skärpt person som jag känner på något sätt. Av språkförenklingsskäl kallas skribenten i det nedanstående för X.

I sin första postning, Programförklaring, förklarar X sin syn på bloggningen:


[D]et som ligger bakom bloggexplosionen är snarare attityden hos de flesta bloggare, nämligen att man skriver mest för sin egen och skrivandets skull, och om någon läser eller inte gör egentligen inte så stor skillnad. Den potentiella offentligheten i att bloggen finns på Internet gör förstås att skrivandet känns aningen mer meningsfullt än om texten hamnar i en hemlig bok i en låda, och dör i samma ögonblick som den skrivs, och det är säkert viktigt, för bloggarens fåfänga om inte annat. Men det motsäger inte att bloggen, trots att den är offentlig, finns till i första hand för skribenten och inte för läsarna. Att denna idé sammanfaller med att man har börjat skriva upp och ner är antagligen mest en slump.

Om sin anonymitet:


Jag väljer att inte skylta med mitt namn på bloggen. Inte för att det är någon stor hemlighet utan för att jag inte tycker att det finns någon anledning. De som känner mig vet vem jag är, och om ni inte känner mig skulle mitt namn ändå inte säga er någonting, förutom att ni kanske skulle förväxla mig med någon av de två halvkända personer som har samma namn.


Om vad som kommer att hända framgent på bloggen:


Det dominerande ämnet, åtminstone till en början, kommer att vara cocktails – därav bloggens namn ctail. Att blanda och dricka cocktails är ett intresse jag odlat i ett par år, men som ingen jag känner delar i nämnvärd grad.

...

Utöver cocktailinlägg är min tanke att här ska dyka upp annan kuriös eller användbar information om ämnen jag utforskat eller funderat över, vilket lär bli en blandning av huvudsakligen ytliga ämnen, såsom andra drycker, mat och musik, men med ett och annat djupare politiskt eller filosofiskt inlägg.

Skulle ämnena helt glida ifrån cocktailämnet så funkar namnet ju ändå: bloggen blir då i sig en cocktail av mina intressen och åsikter.


Några ämnen som behandlas är t.ex.
- Digital musik och mp3-avkodningens mysterier
- vår (o)förmåga att förstå statistiska argument i Den statistiska lögnmarginalen
- genomgång av olika dryckeskonster: Arak och annan anissprit, Dry Martini (så att vi får det avklarat) och samt en trevlig analys Det urvattnade arvet efter agent 007.


Jag delar inte X:s passion för cocktails, däremot är det intressant att läsa personer som skriver passionerat om sina intressen.

Posted by hakank at 06:40 EM Posted to Blogging | Comments (2)

april 02, 2007

Artikel i Impuls om bloggning (där man råkar vara med)

Erik Starck (Framtidstanken) och undertecknad blev för några veckor sedan intervjuade för magasinet Impuls (mer info nedan). Det var en lång och trevlig session med gott sällskap (och god mat för vi träffades naturligtvis på Kin Long).

Tidningen finns att läsa på nätet och i skrivande stund når man numret via förstasidan.

Artikeln (sidan 20-21) är en av flera artiklar om svenska bloggare (börjar på sidan 18). Där finns - förutom Erik och undertecknad - även följande (länk till respektive blogg):
Eva Persson: Eva
Sara Kjellberg:sakj - Sara Kjellberg's blog
Käthe Nilsson: Käthes modeblogg samt Spinn! - din kattidning på nätet!

Det är alltså en salig blandning av bloggar/bloggare. Precis som på rikigt...


Mer om tidningen Impuls:

Impuls ges ut av SV, Studieförbundet Vuxenskolan. SV vill ge människor möjligheter genom att erbjuda studiecirklar, kulturaktiviteter och mötesplatser!

Posted by hakank at 07:30 EM Posted to Blogging | Comments (1)