7. Lær at Programmere

Sæt og gentagere 

 Sæt og Gentagere (Arrays og Iterators)


 Lad os skrive et program som beder os skrive så mange ord som vi ønsker (et ord pr linie, man fortsætter indtil vi trykker enter i en tom linie ), og som så gentager ordene tilbage til os i alfabetisk orden. Ok?

Så ... først vil vi ... øhm... Jae, vi kan jo ... um ...

 Ved du hvad, jeg tror ikke vi kan lave det. Vi har behov for en måde at gemme et ukendt antal ord, og hvordan man holde styr på dem alle sammen, så de ikke bliver blandet op med andre variable. Vi må lægge dem i en slags liste. Vi har behov for et
sæt (array).

Et sæt er bare en liste i din computer. Hver plads i listen fungerer som en variabel: du kan se hvilket objekt en bestemt plads peger på, og du kan få den til at pege på et andet objekt. Lad os kigge på nogle sæt(arrays):


[]
[5]
['Goddag','Farvel']

krydderi = 'vanillie'             # Det er selvfølgelig ikke noget sæt
[89.9, krydderi, [true, false]]  #  ...men dette er.

 I første linie har vi et tomt sæt, så et sæt der holder et enkelt tal, så et sæt  der indeholder to strenge. Derefter har vi en almindelig tildeling. Derefter et sæt der indeholder tre objekter, hvoraf den sidste selv er et sæt[true,false]. Husk variable er ikke objekter, så vores sidste sæt peger i virkeligheden på en float, en streng og et sæt. Selv om vi skulle ville ændre krydderi til noget andet ville det ikke ændre sættet.

 For at hjælpe os til at finde et bestemt objekt i et sæt, er hver plads givet et indextal. Programmører (og de fleste matematikere, tilfældigvis) starter med at tælle fra 0, så vores første plads i sættet er plads 0. Her er hvordan vi ville henvise til objekter i vores sæt:

navne= ['Anna', 'Bente', 'Cristina']

puts navne
puts navne[0]
puts navne[1]
puts navne[2]
puts navne[3]  #  This is out of range.


Anna
Bente
Cristina
Anna
Bente
Cristina
nil



 Vi ser altså  at 'puts navne'  printer hvert navn i sættet 'navne'.  Og  bruger vi 'puts navne[0] til at printe  det 'første' navn i sættet og 'puts navne[1]' til at printe den anden.  Jeg er sikker på at dette ser forvirrende ud men du vil vænne dig til det. Du må i virkeligheden bare vænne dig til at starte med at tælle fra 0 og stoppe med at bruge ord som 'første' og 'anden'. Hvis du taler om et måltid med 5 retter  så lad være med at tale om den første ret. Tal om ret nul (og inde  i hovedet tænker du ret[0].  Du har 5 fingre på din højre hånd og deres numre er:  0, 1,2,3,4. Min kone og jeg er jonglører. Når vi jonglerer med 6 kegler,  jonglerer vi med kegle 0-5. Forhåbentlig vil vi i løbet af nogle få måneder  være i stand til at jonglere med kegle 6 (og således jonglere med 7 kegler imellem os). Når du betynder at bruge ordet 'nulte' så har du fat i det. Ja, 'nulte' ér et rigtigt ord, spørg en programmør eller en matematiker.


 Til sidst forsøgte vi med navne[3] bare for at se hvad der skete. Regnede du med at få en fejl? Nogle gange når du stiller et spørgsmål, så giver det ikke mening (i al fald ikke for computeren) . Så får du en fejl. Andre gange kan du dog komme til at stille et spørgsmål hvor svaret er 'ingenting'. Hvad er der  på plads 3?  Intenting. Hvad er så navne[3] ? 'nil' som er rubys måde at sige 'ingenting' på. 'nil' er et specielt objekt som faktisk betyder 'ikke noget andet objekt'.

Hvis alle disse underlige nummereringer af sæt-pladser er irriterende, skal du ikke være bekymret. Vi kan ofte helt undgå dem ved at bruge nogle sætmetoder, som forekempel denne her:

 Metoden each


 Med 'each' kan vi udføre en handling på hvert (each) objekt der peges på i sættet. Så hvis vi ønsker at sige noget pænt om hvert sprog i sættet nedenunder, så ville vi gøre sådan her:

sprog = ['engelsk', 'tysk', 'ruby']

 sprog.each do |var|
  puts 'Jeg elsker  ' + var + '!'
  puts 'Gør du også det ?'
end

puts 'Og dette gælder også for  C++!'
puts '...'


Jeg elsker engelsk!
Gør du også det ?
Jeg elsker tysk!
Gør du også det ?
Jeg elsker ruby!
Gør du også det ?
Og dette gælder også for C++!

...

 Så hvad skete der lige her? Jo, vi var i stand til at gennemgå hvert objekt i sættet uden at bruge tal, smart, ikke ?  På dansk kan vi forklare det sådan her: For hvert objekt i sættet 'sprog',  peg med variablen var på objektet og gør alt hvad jeg siger du skal, indtil du er færdig med den sidste. (Jeg skulle måske lige sige at C++ er et andet programmerings  sprog. Det er meget sværere at lære end ruby. Normalt  vil et C++ program være mange gange længere end et ruby program selv om de vil udføre det samme).

 Nu tænker du måske: "Dette ligner godtnok meget de løkker (loops) som vi tidligere lærte om". Og ja, det ligner. En vigtig forskel er at metoden 'each' er bare dette: en metode. 'while' og 'end' (og på samme måde de andre ord med fed skrift: do. if. else mv.(Ups... jeg har vist ikke været helt opmærksom på dette hele vejen igennem bogen, hvad der er med fed og hvad der burde være med andre farver... oversætterens anmærkning. )) er ikke motoder. De er grundlæggende dele af ruby sproget, præcis som = og paranteser; lidt ligesom tegnsætning på dansk.

 Men ikke 'each'. 'each' er bare en almindelig sæt -metode.  Metoder som each der opfører sig som loops kaldes ofte for gentagere (iteratorer).

Læg mærke til at gentagere (iteratorer) altid efterfølges af 'do' ...'end'. 'while' og 'if' har aldrig nogen 'do' tæt ved dem. Vi bruger kun dem med gentagere.

Her er en anden lille smart gentager, men det er ikke en sæt metode... det er en integer metode!

3.times do
  puts 'Hip-Hip-Hurra!'
end

Hip-Hip-Hurra!
Hip-Hip-Hurra!
Hip-Hip-Hurra!

 Flere sæt metoder


Så vi har lært om 'each' men der er flere sæt metoder ... nærmest ligeså mange som der er streng metoder! Faktisk  virker nogle af dem (som length, reverse, +, og * ) ligesom de gør for strenge, undtagen at de virker på pladser i et sæt i stedet for bogstaver i en streng. Andre som 'last' og 'join' er specielle for sæt. Medens en helt tredje gruppe, som 'pop' og 'push' faktisk ændrer sættet. Og ligesom med streng metoderne behøver du ikke huske dem alle, så længe som du bare kan huske hvor kan finde ud af noget om dem (lige her).

Først lad os se på to_s og join. join virker ligesom to_s, hvis man lige ser bort fra at den lægger en streng ind imellem sættets objekter. Lad os se på det:


madvarer = ['artiskok', 'broccoli', 'karamelstang']

puts madvarer
puts
puts madvarer.to_s
puts
puts madvarer.join(', ')
puts
puts madvarer.join('  :)  ') + '  8)'

200.times do
  puts []
end

artiskok
broccoli
karamelstang

artiskokbroccolikaramelstang

artiskok, broccoli, karamelstang

artiskok  :)  broccoli  :)  karamelstang  8)




 Som du kan se behandler 'puts' sæt anderledes end andre objekter: den kalder bare 'puts' på hvert objekt i sættet. Det er grunden til at hvis man "puts'er" et tomt sæt 200 gange så sker der ingenting. Et sæt  der ikke peger på noget har ikke noget at "puts'e"  (At gøre ingenting  200 gange er stadig ingenting) Prøv at "puts'e" et sæt der  indeholder  andre sæt. Gør den hvad du forventer ?

Lagde du forresten mærke til at jeg udelod de tomme strenge apostrofferne)  da jeg ville lave en tom linie? De to udtryk udfører den samme ting.


Lad os nu se lidt på 'push','pop' og 'last'. Metoderne 'push' og 'pop' er en slags modsætninger lidt ligesom + og - . 'push' lægger et objekt til slutningen af dit sæt og 'pop' fjerner det sidste objekt i sættet (og fortæller dig hvad det var). 'last' ligner 'pop' fordi den fortæller dig hvad der er i slutningen af sættet men den fjerner det ikke. 'push' og 'pop' ændrer faktisk sættet.

farvoritter = []
farvoritter.push 'regndråber på roser'
farvoritter.push 'whisky på killinger'

puts farvoritter[0]
puts farvoritter.last
puts farvoritter.length

puts farvoritter.pop
puts farvoritter
puts farvoritter.length

regndråber på roser
whisky på killinger
2
whisky på killinger
regndråber på roser
1


 Nogle få ting du bør prøve

* Skriv programmet vi talte om i starten af dette kapitel.
  Tip: Der er en dejlig sæt metode som vil give dig en sorteret version af et sæt: 'sort'. Brug den!
* Forsøg at skrive det ovennævnte program uden at bruge 'sort' metoden. En stor del af at programmere er at løse problemer. Så øv dig så meget som du kan!

* Skriv Indholds programmet igen (fra kapitlet om metoder). Start programmet med et sæt som holder alle informationen  for dit indhold (kapitel navne, side tal, etc) Print så informationen ud i en smukt formateret Indholdsfortegnelse.

Indtil nu har vi lært en hel del metoder. Det er på tide du lærer hvordan du skriver dine egne.

Af Chris Pine

oversat af Gunner Carstens

Original tekst

Indledning

Kapitel 1 - Tal

Kapitel 2 -Bogstaver

Kapitel 3 Variable og tildelinger

Kapitel 4 Blande det hele sammen

Kapitel 5 Mere om metoder

Kapitel 6 Kontrol med strømmen

Kapitel 7 Sæt og Gentagere

Kapitel 8 Skriv dine egne metoder

Kapitel 9 Klasser

Kapitel 10 Blokke og Procs

Kapitel 11 Hvad nu?