Programmering i Ruby

Den Pragmatiske Programmerers Veiledning

Forrige < Innhold ^
Neste >

Ruby.new



Da vi opprinnelig skrev denne boka, hadde vi store planer (vi var yngre da). Vi ønsket å dokumentere språket fra topp til bunn, ved å starte med klasser og objekter og avslutte med detaljene i syntaksen. Det virket som en god ide. Tross alt, så er jo nesten alt i Ruby et objekt og da er det jo fornuftig å ta for oss objekter først.

Trodde vi.

Det viste seg dessverre å være vanskelig å beskrive et språk på denne måten. Har du ikke dekket strenger, if-setninger, tilordning og andre detaljer, blir det vanskelig å lage eksempelklasser. Underveis i vår "ovenfra-og-nedover" beskrivelse kom vi stadig innom detaljer vi måtte dekke slik at kodeeksemplene ble fornuftige.

Derfor klekket vi ut nok en stor plan (de kaller oss ikke pragmatiske uten grunn). Vi skulle fremdeles til å beskrive Ruby fra toppen. Men før vi startet på det, skulle vi legge til et kort kapittel som beskriver alle de vanligste egenskapene til språket, som vi benytter i eksemplene, samt introduserer det Ruby-spesifikke ordforrådet, en slags mini-introduksjon for å få sparket igang resten av boken.

Ruby er et objekt-orientert språk

La oss gjenta det. Ruby er et genuint objekt-orientert språk. Alt du kan håndtere er objekter og resultatene er også objekter. Men det er mange språk som påberoper seg akkurat det samme og de har ofte en annen tolkning av hva objekt-orientert betyr, samt en annen terminologi for konseptene de benytter seg av.

La oss derfor vente med å gå inn i detaljene inntil vi har sett på de termer og notasjonsformer vi vil bruke.

Når du skriver objekt-orientert kode, ønsker du som oftest å modellere deler av virkeligheten på et konseptuelt nivå i koden din. I denne modelleringsprosessen vil du typisk oppdage kategorier av ting som må representeres i kode. Konseptet ``sang'' kan være en slik kategori, i forbindelse med en jukeboks. I Ruby definerer du en klasse til å representere hver av disse entitetene. En klasse kombinerer tilstand (slik som navnet på sangen) og metoder som bruker den tilstanden (kanskje en metode for å avspille sangen).

Når du har disse klassene, ønsker du gjerne å lage et antall instanser av hver av dem. For jukeboksens system vil du ha forskjellige instanser av Sang for populære låter som ``Ruby Tuesday,'' ``Enveloped in Python,'' ``String of Pearls,'' ``Small talk,''og så videre. Ordet objekt brukes i betydningen klasseinstans (og vil antagelig bli brukt oftere, grunnet latskap).

I Ruby blir disse objektene laget ved å kalle en konstruktør, en spesiell metode assosiert med en klasse. Den vanlige konstruktøren kalles new.

song1 = Song.new("Ruby Tuesday")
song2 = Song.new("Enveloped in Python")
# og så videre

Disse instansene er begge utledet fra samme klasse, men de har unike karakteristika. For det første har hvert enkelt objekt en unik objektidentifikator (forkortes til objekt id). For det andre kan du definere instansvariabler som holder ulike verdier for de ulike instansene. Disse instansvariablene utgjør objektets tilstand. For eksempel vil hver av sangene våre ha en instansvariabel som inneholder sangens tittel.

I de forskjellige klassene kan du definere instansmetoder. En metode er en bit funksjonalitet som kan kalles fra inne i klassen og (avhengig av tilgangsbegresninger) fra utsiden av klassen. Disse instansmetodene har tilgang til objektets instansvariabler, og dermed også tilstanden til objektet.

Metoder kjøres ved at en melding sendes til objektet. Meldingen inneholder metodens navn og eventuelle parametre. [Ideen om å uttrykke metodekall som meldinger kommer i fra Smalltalk.] Når et objekt mottar en melding, slår det opp i sin klasse for å finne den aktuelle metoden. Hvis metoden finnes, blir den kalt. Vi kommer tilbake til hva som skjer dersom metoden ikke finnes.

Alt dette snakket om metoder og meldinger kan virke overveldende, men er veldig naturlig i praktisk bruk. La oss ta en titt på en håndfull metodekall. (Minner om at pilene i eksemplene viser verdiene som uttrykkene returnerer.)

"gin joint".length » 9
"Rick".index("c") » 2
-1942.abs » 1942
sam.play(aSong) » "duh dum, da dum de dum ..."

Det foran punktumet kalles mottakeren, og navnet etter punktumet angir metoden som skal kalles. Det første eksempelet spør en streng hvor lang den er, og det andre spør en annen streng om indeksen for bokstaven ``c''. Tredje linjen får et tall til å regne ut sin absoluttverdi. Til slutt ber vi Sam om å spille en sang for oss.

Det er verdt å merke seg en stor forskjell mellom Ruby og de fleste andre språk. I (for eksempel) Java sender du inn tallet til en separat funksjon for å regne ut dets absoluttverdi. Du skriver for eksempel

number = Math.abs(number)     // Java kode

I Ruby er tall selv ansvarlige for å finne sin egen absoluttverdi og tar seg av detaljene internt. Du sender bare meldingen abs til et tallobjekt og lar det gjøre arbeidet.

nummer = nummer.abs

Dette gjelder alle Ruby objekter; i C ville du skrevet strlen(navn), mens i Ruby blir det navn.length. Dette er en del av hva vi mener med at Ruby er et genuint objekt-orientert språk.

Litt grunnleggende Ruby

De færreste liker å lese haugevis av syntaksregler når de begynner å lære et nytt språk. Derfor jukser vi. I denne biten vil vi gå innom noen av høydepunktene, det du vite for å kunne skrive programmer i Ruby. Senere, i kapittel 18, som begynner på side 199, vil vi gå inn i alle detaljene.

La oss starte med et enkelt Ruby program. Vi skriver en metode som returnerer en streng med et navn lagt til på slutten. Deretter kaller vi denne metoden et par ganger.

def sayGoodnight(name)
  result = "Goodnight, " + name
  return result
end

# Sengetid... puts sayGoodnight("John-Boy") puts sayGoodnight("Mary-Ellen")

Først, noen generelle observasjoner. Syntaksen til Ruby er ren. Du trenger ikke semikolon for å avslutte et uttrykk dersom du har hvert uttrykk på en egen linje. Kommentarer i Ruby starter med # tegnet og varer ut til slutten av linjen. Hvordan du legger opp koden er i stor grad opp til deg; indentering har ingen betydning.

Metoder defineres med def nøkkelordet, fulgt av metodens navn (i dette tilfellet ``sayGoodnight'') og dens parametre mellom parenteser. Ruby bruker ikke krøllparenteser rundt metodekroppen. I stedet avslutter du bare metodekroppen med nøkkelordet end. Vår metodes kropp er ganske enkel. Den første linja slår sammen en ordrett streng, ``Goodnight,[visible space]'', til parameteren name og tilordner resultatet til den lokale variabelen result. Den neste linjen returnerer det resultatet til den som kalte metoden. Legg merke til at vi ikke trengte å deklarere variabelen result; den ble til når vi tilordnet en verdi til den.

Etter å ha definert metoden, kaller vi den to ganger. I begge tilfeller sender vi resultatet til metoden puts, som skriver ut resultatet fulgt av linjeskift.

Goodnight, John-Boy
Goodnight, Mary-Ellen

Linjen ``puts sayGoodnight("John-Boy")'' inneholder to metodekall. Først kalles sayGoodnight og deretter puts. Hvorfor har det ene metodekallet argumentene sine i parenteser og ikke den andre? I dette tilfellet er det opp til smak og behag. De følgende linjene gjør alle det samme.

puts sayGoodnight "John-Boy"
puts sayGoodnight("John-Boy")
puts(sayGoodnight "John-Boy")
puts(sayGoodnight("John-Boy"))

Dessverre er ikke livet alltid så enkelt, og regler for presedens kan gjøre det vanskelig å forstå hvilket argument som går til hvilket metodekall. Derfor anbefaler vi å bruke parenteser, med mindre metodekallet er veldig enkelt.

Eksempelet vårt viser også noen strenger i Ruby. Det er flere måte å lage en streng på, men det vanligste er nok å skrive tekst ordrett inn i programmet, det vil si en rekke av tegn mellom apostrofer eller kråketær. Forskjellen mellom de to formene er hvor mye prosessering Ruby gjør med strengen under konstruksjon. I tilfellet med apostrofer, gjør Ruby veldig lite. Med noen få unntak, blir strengen det du skriver.

Ved bruk av kråketær gjør Ruby mer arbeid. Først ser det etter substitusjoner---sekvenser som starter med en bakvendt skråstrek (backslash)---og bytter dem ut med en binær verdi. Den vanligste av disse er ``\n'', som blir byttet ut med linjeskift.

puts "And Goodnight,\nGrandma"
produserer:
And Goodnight,
Grandma

Videre gjør Ruby interpolering av uttrykk i strenger angitt mellom kråketær. Inne i selve strengen blir sekvensen #{ uttrykk } byttet ut med verdien av uttrykk. Vi kunne brukt dette til å omskrive den forrige metoden vår.

def sayGoodnight(name)
  result = "Goodnight, #{name}"
  return result
end

Når Ruby lager dette strengobjektet, ser det på den nåværende verdien til name og setter det inn i strengen. Uttrykkene du bruker i #{...} kan være så komplekse du bare vil. En snarvei gjør at du slipper å skrive krøllparentesene når uttrykket kun er en global-, instans- eller klassevariabel. For mer informasjon om strenger og andre standard typer i Ruby, se kapittel 5, som begynner på side 47.

Til slutt kan vi forenkle denne metoden litt til. En metode i Ruby returnerer den verdien som det siste uttrykket evaluerer til, så vi trenger egentlig ikke return i metoden vår.

def sayGoodnight(name)
  "Goodnight, #{name}"
end

Vi lovte at denne delen skulle bli kort. Vi har bare et emne til å dekke: navn. Vi bruker noe terminologi (f.eks. klassevariabel) som vi ikke kommmer til å definere ennå, for å unngå å bruke for mye plass. Men ved å nevne reglene nå, vil du være bedre forberedt når vi senere begynner å snakke om instansvariabler og lignende.

Ruby har en konvensjon som hjelper oss til å forstå bruken til et navn: de første tegnene i et navn angir hvordan navnet brukes. Lokale variabler, metodeparametre og metodenavn bør alle begynne med en liten bokstav eller understrekningstegn (underscore). Globale variabler prefikses med et dollartegn ($), mens variabler tilhørende en instans bgynner med ett ``at'' tegn (@). Klassevariabler starter med to ``at'' tegn (@@). Til sist, navn på klasser, moduler og konstanter bør begynne med en stor forbokstav. I tabell 2.1 på side 10 kan du se eksempler på forskjellige typer navn.

Etterfulgt av det første tegnet, kan et navn bestå av enhver kombinasjon av bokstaver, tall og understrekningstegn (med det unntak tall ikke kan følge rett etter @ tegnet).

Eksempelnavn på variabler og klasser
Variabler Konstanter og
Lokale Globale Instans Klasse Klassenavn
name $debug @name @@total PI
fishAndChips $CUSTOMER @point_1 @@symtab FeetPerMile
x_axis $_ @X @@N String
thx1138 $plan9 @_ @@x_pos MyClass
_26 $Global @plan9 @@SINGLE Jazz_Song

Array og Hash

I Ruby er både tabeller (Array) og hashtabeller (Hash) indekserte samlinger av objekter. Begge holder sammen en mengde objekter, som man kan få tak i ved bruk av en nøkkel. Når man bruker en tabell, er nøkkelen et heltall, mens når man bruker en hashtabell kan ethvert objekt brukes som nøkkel. Både tabeller og hashtabeller vokser etter behov når nye elementer legges til. Det går raskere å aksessere elementer i en tabell, men hashtabeller tilbyr mer fleksibilitet. En enkelt tabell eller hashtabell kan inneholde objekter av varierende typer; du kan ha en tabell som inneholder et heltall, en tekststreng og et flyttall, som vi snart får se.

Du kan lage og initialisere en ny literal tabell rett i kildekoden---bare sett en rekke elementer adskilt med komma inne i hakeparenteser. Når du så har et Array-objekt, får du tak i de individuelle elementene ved å gi en indeks i hakeparenteser, som det neste eksempelet viser.

a = [ 1, 'cat', 3.14 ]   # Array med tre elementer
# hent det første elementet
a[0] » 1
# sett det tredje elementet
a[2] = nil
# dump Array-objektet 
a » [1, "cat", nil]

Du kan lage tomme tabeller enten ved å sette inn tomme hakeparenteser eller ved å kalle konstruktøren til Array, Array.new .

empty1 = []
empty2 = Array.new

Noen ganger kan det være tungvint å lage tabeller som inneholder ord, da man må separere med komma og sitere ordene med kråketær. Heldigvis finnes den en snarvei: %w som hjelper oss med dette.

a = %w{ ant bee cat dog elk }
a[0] » "ant"
a[3] » "dog"

Hashtabeller ligner på vanlige tabeller. For å lage en literal hashtabell direkte i kildekoden brukes krøllparenteser, ikke hakeparenteser. Videre må to objekter legges inn for hvert element: en for nøkkelen, den andre for verdien.

Som et eksempel, ønsker du kanskje å koble musikkinstrumenter til deres plassering i orkesteret. Dette kan du gjøre med en hashtabell.

instSection = {
  'cello'     => 'string',
  'clarinet'  => 'woodwind',
  'drum'      => 'percussion',
  'oboe'      => 'woodwind',
  'trumpet'   => 'brass',
  'violin'    => 'string'
}

Hashtabeller indekseres med samme notasjon som vanlige tabeller, det vil si hakeparenteser.

instSection['oboe'] » "woodwind"
instSection['cello'] » "string"
instSection['bassoon'] » nil

Vi ser i det siste eksempelet at en hashtabell returnerer standardverdien nil når man gir den en nøkkel den ikke inneholder. Ofte er dette praktisk, da nil betyr false i logiske uttrykk. Men noen ganger kan du ønske å endre denne oppførselen. For eksempel, dersom du bruker en hashtabell til å telle antall forekomster av en nøkkel, er det mer praktisk om tallet null returneres når nøkkelen ikke finnes. Dette kan enkelt gjøres ved å angi en standardverdi når man lager et nytt, tomt Hash-objekt.

histogram = Hash.new(0)
histogram['key1'] » 0
histogram['key1'] = histogram['key1'] + 1
histogram['key1'] » 1

Array og Hash tilbyr et bredt spekter av metoder: les diskusjonen som starter på side 35 og bla i referanseseksjonene som starter på sidene 278 og 317 for øvrige detaljer.

Flytkontroll strukturer

Ruby tilbyr alle de vante strukturene for flytkontroll, slik som if-setninger og while-løkker. Java, C og Perl programmerere kan bli noe overrasket over mangelen på krøllparenteser. Ruby bruker i stedet nøkkelordet end for å angi slutten på en sammenhengende bolk med kode.

if count > 10
  puts "Try again"
elsif tries == 3
  puts "You lose"
else
  puts "Enter a number"
end

Likeså avsluttes while setninger med end.

while weight < 100 and numPallets <= 30
  pallet = nextPallet()
  weight += pallet.weight
  numPallets += 1
end

Ruby sine setningsmodifikatorer er et nyttig alternativ dersom kroppen til en if eller while-setning kun er et enkelt uttrykk. Da kan man bare skrive uttrykket, fulgt av if eller while fulgt av det logiske uttrykket. Her følger en enkel if-setning.

if radiation > 3000
  puts "Danger, Will Robinson"
end

Her er samme koden, omskrevet med en setningsmodifikator.

puts "Danger, Will Robinson" if radiation > 3000

Likedan kan en while-løkke som

while square < 1000
   square = square*square
end

omskrives til det mer kompakte uttrykket

square = square*square  while square < 1000

Perl programmerere er antagelig kjent med disse setningsmodifikatorene.

Regulære uttrykk

Mesteparten av de innebygde typene i Ruby vil virke kjent til alle programmerere. Majoriteten av programmeringsspråk har strenger, heltall, flyttall, tabeller og lignende. Men inntill Ruby dukket opp, var støtte for regulære uttrykk som oftest bare innebygd i de såkalte skriptingspråkene, deriblant Perl, Python og awk. Dette er litt synd, da regulære uttrykk utgjør et kraftig verktøy for behandling av tekst, selv om de er kryptiske.

Det finnes egne bøker dedikert til regulære uttrykk (slike som Mastering Regular Expressions ) og vi vil ikke forsøke å dekke alt i et lite avsnitt. I stedet ser vi på en håndfull brukseksempler av regulære uttrykk. En komplett oversikt over regulære uttrykk finner du på side 58 og utover.

Et regulært uttrykk er i bunn og grunn en måte å angi et mønster av tegn man vil finne maken til i en streng. I Ruby kan du lage et regulært uttrykk ved å skrive et mønster mellom to skråstrek-tegn. Og siden Ruby er Ruby, er regulære uttrykk selvfølgelig objekter og kan behandles deretter.

For eksempel kan du skrive et mønster som slår ut på en streng som inneholder teksten ``Perl'' eller teksten ``Python'' ved å bruke følgende regulære uttrykk.

/Perl|Python/

Skråstrek-tegnene angir hva som er med i mønsteret, som består av de to ordene vi vil gjenkjenne, som adskilles med en vertikal strek (``|''). Inne i mønstrene kan du benytte parenteser på samme måte som i aritmetiske uttrykk. Det betyr at du også kunne ha skrevet mønsteret slik

/P(erl|ython)/

Du kan også angi repetisjoner i mønstre. /ab+c/ slår ut på en streng som inneholder en ``a'' fulgt av en eller flere ``b''-tegn, fulgt av en ``c''. Bytt ut pluss med stjerne og /ab*c/ lager et regulært uttrykk som slår ut på en ``a'', null eller flere ``b''-er, og en ``c''.

Du kan også sammenligne mot en gruppe av tegn i et mønster. Noen vanlige eksemler er tegn-klasser som ``\s'', som tilsvarer mellomromstegn (mellomrom, tabulator, linjeskift og lignende), ``\d'', som tilsvarer ethvert siffer og ``\w'', som tilsvarer ethvert tegn som brukes i typiske (engelske) ord. Punktum ``.'' tilsvarer et vilkårlig tegn.

Vi kan kombinere alle disse og komme ut med noen nyttige regulære uttrykk.

/\d\d:\d\d:\d\d/     # et tidspunkt som f.eks. 12:34:56
/Perl.*Python/       # Perl, null eller flere andre tegn, dernest Python
/Perl\s+Python/      # Perl, en eller flere mellomrom, dernest Python
/Ruby (Perl|Python)/ # Ruby, et mellomrom, og enten Perl eller Python

Når du først har gjort deg bryet med å lage et mønster, er det synd å la det gå til spille. Operatoren ``=~'' kan brukes for å se om noen del av en streng passer mønsteret. Dersom mønsteret finnes i strengen, returnerer kallet til =~ indeksen i strengen hvor mønsteret starter eller nil hvis mønsteret ikke ble funnet. Dette gjør at du kan bruke regulære uttrykk som logisk uttrykk i if og while setninger. For eksempel skriver følgende kodebit ut en melding hvis en streng inneholder 'Perl' eller 'Python'.

if line =~ /Perl|Python/
  puts "Scripting language mentioned: #{line}"
end

Den delen av en streng som passer inn i et mønster kan også bli byttet ut med en annen tekst ved hjelp av en av substitusjonsmetodene i Ruby.

line.sub(/Perl/, 'Ruby')    # bytt første 'Perl' ut med 'Ruby'
line.gsub(/Python/, 'Ruby') # bytt alle 'Python' ut med 'Ruby'

Vi vil ha mer å si om regulære uttrykk etterhvert i boken.

Blokker og iteratorer

Her beskriver vi kjapt en av Ruby sine spesielle styrker. Vi skal til å se på kodeblokker: kodebiter som kan assosieres med metodekall, omtrent som om de var parametre. Dette er et kraftig verktøy. Du kan bruke kodeblokker til å implementere tilbakekall (callbacks) (men de er enklere enn anonyme, indre klasser i Java), sende rundt kodebiter (men de er mer fleksible enn C sine funksjonspekere) og implementere iteratorer.

Kodeblokker er ikke stort mer enn litt kode mellom krøllparenteser eller do...end.

{ puts "Hello" }       # dette er en blokk

do                     #   club.enroll(person)  # dette er også en blokk   person.socialize     # end                    #

Når du har laget en blokk kan du assosiere den med et metodekall. Den metoden kan da kalle koden i blokken en eller flere ganger ved å bruke Ruby sin yield-setning. Det følgende eksempelet viser dette i praksis. Vi definerer en metode som kaller yield to ganger. Deretter kaller vi metoden og legger en blokk til på samme linjen, etter metodekallet (og etter eventuelle argumenter til metoden). [ Noen liker å tenke på assosieringen av en blokk til en metode som en type parameter som blir sendt med. Dette forklarer ikke hele historien. Du vil være nærmere sannheten om du tenker på blokken og metoden som korutiner, som gir kontrollflyten frem og tilbake mellom seg. ]

def callBlock
  yield
  yield
end

callBlock { puts "In the block" }
produserer:
In the block
In the block

Legg merke til at koden i blokken (puts "In the block") blir kjørt to ganger, en gang for hvert kall til yield.

Du kan gi parametre til yield kallet: disse vil bli sendt til blokken. Inne i blokken lister du opp navnene på argumentene du vil bruke for å motta disse parametrene mellom loddrette streker. (``|'').

  def callBlock
    yield , 
  end

  callBlock { |, | ... }

Kodeblokker brukes gjennom hele biblioteket til Ruby for å implementere iteratorer: metoder som løpende returnerer elementer fra en eller annen form for samling av objekter, som for eksempel en tabell.

a = %w( ant bee cat dog elk )    # lag en tabell
a.each { |animal| puts animal }  # iterer over innholdet 
produserer:
ant
bee
cat
dog
elk

La oss se nærmere på hvordan vi kunne implementert Array-klassens each iterator som vi brukte i det forrige eksempelet. Iterator-metoden each går over alle elementene i tabellen og kaller yield for hvert enkelt av dem. I pseudokode kan det se ut slik:

# inne i Array klassen...
def each
  for each element
    yield(element)
  end
end

Du kan da gå over innholdet i en tabell ved å kalle each metoden og angi en blokk. Blokken vil bli kalt for hvert element etter tur.

[ 'cat', 'dog', 'horse' ].each do |animal|
  print animal, " -- "
end
produserer:
cat -- dog -- horse --

På samme måte er mange løkkekonstruksjoner, som er innebygd i språk som C og Java, ikke noe mer enn metodekall i Ruby, hvor metodene benytter den angitte blokken ingen, en eller flere ganger.

5.times {  print "*" }
3.upto(6) {|i|  print i }
('a'..'e').each {|char| print char }
produserer:
*****3456abcde

Her ber vi tallet 5 om å kalle en blokk fem ganger. Deretter ber vi tallet 3 om å kalle en blokk med påfølgende høyere tallverdier opp til og med 6. Til slutt, kaller rekken av bokstaver fra ``a'' til og med ``e'' en blokk ved hjelp av each metoden.

Lesing og skriving

Det følger et utfyllende innput/utput bibliotek med Ruby. I mesteparten av boken vil vi derimot holde oss til noen få enkle metoder. Vi har alt sett to metoder som sender utput. Metoden puts skriver ut alle argumentene den får, med linjeskift etter hver av dem. Metoden print skriver også ut sine argumenter, men uten linjeskift. Begge kan brukes for å skrive til hvilket som helst I/O objekt, men til vanlig skriver de ut til konsollet.

En annen metode for utput som vi ofte bruker er printf, som skriver ut argumentene i et format styrt av en formatteringsstreng (akkurat slik som printf gjør i C eller Perl).

printf "Number: %5.2f, String: %s", 1.23, "hello"
produserer:
Number:  1.23, String: hello

I dette eksempler forteller formatteringsstrengen "Number: %5.2f, String: %s" at printf skal sette inn et flyttall (tillatt fem bokstaver totalt, med to desimaler) og en streng.

Det er mange måter å lese inn innput på. Antagelig er den mest tradisjonelle måten å bruke rutinen gets, som gir deg den neste linjen fra standard innput.

line = gets
print line

Kallet til gets har en sideeffekt: i tillegg til å returnere linjen den nettopp hentet inn, lagrer det den også i den globale variabelen $_. Denne variabelen er spesiell, da den brukes som default argument i en del tilfeller. Hvis du kaller print uten noen argumenter, skriver den ut innholdet i $_. Hvis du skriver en if eller while-setning med kun et regulært uttrykk som logisk betingelse, blir det sjekket opp mot $_. Mens noen purister ser på dette som frastøtende og barbarisk, kan disse snarveiene hjelpe deg med å skrive veldig konsise programmer. For eksempel skriver det følgende programmet alle linjene på innputstrømmen som inneholder ordet ``Ruby.''

while gets           # tilordner linje til $_
  if /Ruby/          # sammenligner med $_
    print            # skriver ut $_
  end
end

Den mer korrekte ``Ruby måten'' å skrive dette på, ville vært å bruke en iterator.

ARGF.each { |line|  print line  if line =~ /Ruby/ }

Her benyttes det predefinerte objektet ARGF, som representerer den innputstrømmen som kan leses av et program.

Fremover og oppover

Det var alt. Vi har nådd slutten på vår lynraske dekning av noen av de grunnleggende fasilitetene i Ruby. Vi har tatt et kjapt blikk på objekter, metoder, strenger, samlinger og regulære uttrykk, sett noen enkle konstruksjoner for flytkontroll og tittet på noen ganske smarte iteratorer. Forhåpentligvis vil dette kapittelet ha gitt deg med nok ammunisjon til å kunne angripe resten av boken.

Det er på tide å gå videre, og opp---opp mot nye høyder. I neste omgang vil vi se nærmere på klasser og objekter, som både er høynivå konstruksjoner i Ruby og utgjør grunnlaget for hele språket.

( In progress translation to Norwegian by NorwayRUG. $Revision: 1.31 $ )
$Log: intro.xml,v $
Revision 1.31  2003/09/13 17:52:53  kent
Gjennomgang.

Revision 1.30  2003/01/19 19:32:23  kent
Fikser ting som kom opp i gjennomgang.

Revision 1.29  2002/08/09 08:55:05  kent
Fjernet siste ORIGINAL kommentaren, men fant også et sted hvor
noe var droppet i oversettelsen.


Forrige < Innhold ^
Neste >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide".
Translation to norwegian by Norway Ruby User Group.
Copyright for the english original authored by David Thomas and Andrew Hunt:
Copyright © 2001 Addison Wesley Longman, Inc.
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).

(Please note that the license for the original has changed from the above. The above is the license of the original version that was used as a foundation for the translation efforts.)

Copyright for the norwegian translation:
Copyright © 2002 Norway Ruby User Group.
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.