Ruby/Zmienne lokalne: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
Szymon wro (dyskusja | edycje) Nie podano opisu zmian |
Szymon wro (dyskusja | edycje) Nie podano opisu zmian |
||
Linia 4:
<pre>
irb(main):003:0> a
from (irb):3
</pre>
Linia 24 ⟶ 25:
* cały skrypt (chyba że zastosowano jedno z powyższych)
<source lang="ruby">
a = 44
puts defined?(a) #=> local-variable
loop do
b=45
break
end
puts defined?(b) #=> nil
</source>
Obiekty procedurowe, które żyją w pewnym zakresie widoczności współdzielą tylko te zmienne lokalne, które również należą do tego zakresu. Tutaj, zmienna lokalna <tt>a</tt> jest współdzielona przez <tt>main</tt> oraz obiekty procedurowe <tt>p1</tt> i <tt>p2</tt>:
<source lang="ruby">
a = nil
l1 = lambda {|n| a=n}
l2 = lambda {a}
l1.call(5)
puts a #=> 5
puts l2.call #=> 5
</source>
Zauważ, że nie można pominąć <tt>a = nil</tt> na początku. To przypisanie zapewnia, że zasięg zmiennej <tt>a</tt> obejmie <tt>l1</tt> i <tt>l2</tt>. Inaczej <tt>l1</tt> i <tt>l2</tt> utworzyłyby swoje własne zmienne lokalne <tt>a</tt>, i rezultatem wywołania <tt>l2</tt> byłby błąd "undefined local variable or method" (niezdefiniowana zmienna lokalna lub metoda). Moglibyśmy użyć <tt>a = 0</tt>, ale użycie <tt>nil</tt> jest pewną uprzejmością wobec przyszłych czytelników naszego kodu. Pokazuje naprawdę jasno, że tylko ustanawiamy zakres, ponieważ wartość przypisana do zmiennej nie niesie żadnego specjalnego znaczenia (<tt>nil</tt>).
W rozdziale o [[Roby/Domknięcia i obiekty procedurowe|domknięciach i obiektach procedurowych]] wspomnieliśmy, że domknięcia i obiekty procedurowe zachowują kontekst używanych zmiennych lokalnych. Jest to bardzo potężna zaleta: współdzielone zmienne lokalne pozostają poprawne nawet wtedy, gdy przekazane są poza pierwotny zakres.
<source lang="ruby">
def pudelko
zawartosc = nil
wez = lambda { zawartosc }
wloz = lambda { |n| zawartosc = n }
return wez, wloz
end
odczyt, zapis = pudelko
puts odczyt.call #=> nil
zapis.call(2)
puts odczyt.call #=> 2
</source>
Ruby jest szczególnie sprytny jeśli chodzi o zakres. W naszym przykładzie ewidentnie widać, że zmienna <tt>zawartosc</tt> jest współdzielona pomiędzy <tt>odczyt</tt> i <tt>zapis</tt>. Możemy również wytworzyć wiele par <tt>odczyt-zapis</tt> używając metody <tt>pudelko</tt> zdefiniowanej powyżej. Każda para współdzieli zmienną <tt>zawartosc</tt>, ale pary nie kolidują ze sobą nawzajem. Dopóki istnieją obiekty procedurowe, zachowane są ich konteksty wywołania wraz z odpowiadającymi im zmiennymi lokalnymi!
<source lang="ruby">
odczyt_1, zapis_1 = pudelko
odczyt_2, zapis_2 = pudelko
zapis_1.call(99)
puts odczyt_1.call #=> 99
# w tym pudelku jeszcze nic nie ma
puts odczyt_2.call #=> nil
</source>
<noinclude>
{{ProstaNawigacja|spis=Ruby|poprzart=Ruby/Zmienne instancji|poprz=Zmienne instancji|nastart=Ruby/Stałe klasowe|nast=Stałe klasowe}}
|