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