Utolsó módosítás: 2009. április 23.
A rubyban a szögletes zárójelek, ha önmagukban állnak,
egy új tömböt hoznak létre.
Például a [] kifejezés értéke egy újonnan létrejött tömb,
ami jelenleg üres.
Ez a tömb különbözik az összes eddig létrehozott tömbtől,
tehát ha módosítjuk az elemeit, az a korábbi tömbök elemeit nem módosítja,
és viszont.
Ha a szögletes zárójelek egy kifejezés után állnak,
és annak a kifejezésnek az értéke egy tömb,
akkor a kapott kifejezés a tömb egyik elemét olvassa ki
illetve változtatja meg.
Ha például az s változó jelenlegi értéke egy tömb,
akkor s[0] ennek a tömbnek az első elemét adja vissza,
s[0] = 42 pedig módosítja ezt az elemet.
Egy tömb a ruby-ban írható (mutable) érték, tehát a tartalmát
meg lehet változtatni.
Ha valahol egy tömb értéket tárolunk, például egy lokális változó értékeként,
vagy egy tömb elemeként, stb, akkor ez az érték lényegében csak rámutat
a tömbre, ha később ezen tömb tartalmát (méretét vagy elemeit)
megváltoztatjuk, akkor azon a helyen keresztül,
ahol a tömböt tároltuk, szintén az új tartalmat fogjuk látni.
eltárolhatjuk így, ekkor ezeken keresztül
Így például az a = [0, 0]; b = a; b[0] = 5; utasítások
végrehajtása után az a[0] kifejezés eredménye 5.
Egy olyan utasítás tehát, mint pl. b[0] = 5;
nem változtatja meg a b változó értékét,
az továbbra is ugyanaz a tömb lesz.
Másrészt viszont egy olyan utasítás, mint a b = 9; vagy akár
b = [8, 2]; megváltoztatja a b
értékét, és a régi értéket eldobja;
de annak a tömbnek a tartalmát, ami a b korábbi
értéke volt, nem változtatja meg.
Így ha egy másik változó értéke továbbra is ugyanez a tömb volt,
akkor azon keresztül a régi tömböt érhetjük el.
Például induljunk ki az előző példából: az
a = [0, 0]; b = a; b[0] = 1; utasítások után az
a és a b tartalma ugyanaz a b
tömb, amelyet a p függvény így ír ki: [1, 0].
Ha most a b = [5, 2]; utasítást hajtjuk végre, akkor
a értéke továbbra is a régi tömb, amely így íródik ki:
[1, 0].
(A p függvény kimenetéből csak egy tömb tartalma derül ki,
az nem, hogy két kiírt tömb ugyanaz a tömb-e,
vagy két különböző tömb ugyanazzal a mérettel és azonos kinézetű elemekkel.)
Ráadásul annak a változónak a tartalmát is megváltoztathatjuk,
amibe eleve eltároltuk a tömböt: a = [0, 0]; b = a; után
kiadhatjuk az a = 5; utasítást, de a kételemű tömb megmarad,
mivel egy másik változó, a b hivatkozik rá.
Emlékezzünk rá, hogy C nyelben egy tömböt egy tömb változó
deklarációja hozott létre, és ha ez a változó megszűnt
(mert kiléptünk annak a függvénynek vagy blokknak a futásából,
amiben deklaráltuk a tömböt), akkor a tömb is megszűnik, és az
esetlegesen a tömb elemeikre mutatókon keresztül már nem szabad az elemeire
hivatkozni.
Ezzel ellentétben a ruby-ban a tömb akkor jön létre,
ha a szögletes zárójeles kifejezéssel létre hozzuk,
és később nem szűnik meg létezni.
Ennek a legfontosabb alkalmazása, hogy a ruby-ban egy függvényből könnyen
visszaadhatunk (visszatérési értékként) egy új tömböt,
amit a függvény futása közben hoztunk létre.
A ruby-ban tehát a tömbök (és a sztringek és még néhány
másik fajta érték) módosítható tartalmú.
Ezzel szemben a számok, a logikai (igaz-hamis) értékek, és
még néhány egyéb típusnak nem lehet megváltoztatni a tartalmát,
így ha például azt írjuk, hogy a = 4; b = a, akkor
mindegy, hogy arra gondolunk, hogy a két változó értéke ugyanaz a szám
objektum, vagy két különböző szám objektum azonos tartalommal,
mivel a szám tartalmát semmilyen módon nem lehet megváltoztatni,
tehát b-vel bármit csinálunk, attól a értéke
nem lehet 4 helyett 5.
Nézzünk alkalmazott példákat erre.
meret = 4
matrix = []
(0 ... meret).each {|i|
sor = []
(0 ... meret).each {|j|
sor[j] = i * meret + j
}
matrix[i] = sor
}
print "matrix = "
p matrix
print "matrix[2] = "
p matrix[2]
print "matrix[2][0] = "
p matrix[2][0]
Kimenet:
matrix = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]] matrix[2] = [8, 9, 10, 11] matrix[2][0] = 8
Az első részt írhatjuk így is:
matrix = []
(0 ... meret).each {|i|
sor = []
matrix[i] = sor
(0 ... meret).each {|j|
sor[j] = i * meret + j
}
}
Vagy így.
matrix = []
(0 ... meret).each {|i|
matrix[i] = []
(0 ... meret).each {|j|
matrix[i][j] = i * meret + j
}
}
Vagy akár így.
matrix = []
(0 ... meret).each {|i|
matrix[i] = []
}
(0 ... meret).each {|i|
(0 ... meret).each {|j|
matrix[i][j] = i * meret + j
}
}
Azt nem írhatnánk csak (hibát jelezne), hogy
matrix = []
(0 ... meret).each {|i|
(0 ... meret).each {|j|
matrix[i][j] = i * meret + j
}
}
mivel a matrix[i] értékét nem állítottuk be sehol.
Ha pedig ezt írnánk, akkor hibás kimenetet kapunk, mivel a matrix tömb összes eleme ugyanaz a tömb.
matrix = []
sor = []
(0 ... meret).each {|i|
(0 ... meret).each {|j|
sor[j] = i * meret + j
}
matrix[i] = sor
}
Valóban, lefuttatva a kimenet ez lesz:
matrix = [[12, 13, 14, 15], [12, 13, 14, 15], [12, 13, 14, 15], [12, 13, 14, 15]] matrix[2] = [12, 13, 14, 15] matrix[2][0] = 12