Ruby & Rails: веб-разработка с удовольствием

В предыдущем посте мы затронули важнейшую концепцию — замыкание (closure). Перечитайте этот абзац ещё раз, после того как рассмотрите следующие примеры.
Итак, примеры кода: a = 1 b = lambda { puts a } b.call # напечатает 1 a = 2 b.call # напечатает 2 # ничего страшного в этом примере нет - вполне ожидаемое поведение Пример 2. class Abc attr_accessor :bar def foo @bar ||= 0 x = 5 lambda { puts @bar, x, self.class; } end end x = 10 a = Abc.new b = a.foo b.call # напечатает 0, 5 и Abc a.bar += 1 x = 10 b.call # напечатает 1, 5, и Abc # аттрибут bar объекта a виден из блока b, # сам блок (как переменная) находится в нашем контексте -- является # локальной переменной в нашем контексте; но он видит мир как-бы изнутри # функции foo, где есть @a и своя локальная переменная x, # которая видна и не умирает, несмотря на свою локальность # и тот факт, что выполнение foo давно закончилось. Замыкание происходит для любого блока, как для созданного с помощью lambda, так и для блока, переданного методу, как оформленнного с помощью фигурных скобок, так и с помощью конструкции do ... end. В последнем примере мы вызвали метод foo у экземпляра a некоторого класса Abc. Внутри этого метода инициализируется переменная экземпляра @bar и возвращается блок, который печатает эту переменную, а также значение локальной переменной x и self.class. После выполнения этого кода Вы увидите, как сильно блок привязан к своей родине, все его мысли и побуждения — там. В контексте, в котором выполняется строка "b.call", переменная @bar не видна (лучше сказать, её просто нет в этом контексте). Но тем не менее, выполнение блока b приводит к выводу значений переменной @bar объекта a, который, как будто бы, здесь непричём. Объясняется это тем, что блок создавался в контексте выполнения метода foo объекта a, и в этом контексте были видны все instance-переменные объекта a. Таким образом, внутренний контекст объекта можно вытащить наружу с помощью блока, созданного внутри объекта и переданного как результат некоторой функции наружу. Пример 3. class Abc attr_accessor :block def do_it @a = 1 block.call end end c = 1 a = Abc.new a.block = lambda { puts "c=#{c}"} a.do_it # напечатает 1; # видимость локальной переменной изнутри блока - активно # используемая фича в динамическом программировании a.block = lambda { puts "@a=#{@a.inspect}"} a.do_it # напечатает nil, т.к. @а не инициализирована в нашем контексте, # а именно этот контекст "заключён внутрь" блока a.block. # Хоть выполнение блока a.block запускается внутри метода Abc#foo # контекст Abc#foo неизвестен внутри блока a.block Повторим то же самое, только теперь блок будет создаваться просто как блок, ассоциированный с методом, а не с помощью конструкции lambda: class Abc def do_it(&block) @a = 1 block.call end end c = 1 a = Abc.new a.do_it {puts "c=#{c}"} a.do_it { puts "@a=#{@a.inspect}"} Что такое контекст?Это определёная точка зрения на пространство имен, из которой что-то видно, что-то невидно, а что-то видно по-своему. class Abc attr_accessor :x def inner_block lambda {|x| x * @factor} end end a = Abc.new b = a.inner_block eval("@factor = 7", b.binding) puts b[10] # напечатает 70 eval("@x = 6 * @factor", b.binding) puts a.x # напечатает 42 Но, конечно, так писать не нужно. Для выполнения кода в контексте объекта используйте просто instance_eval: Пример 5. class Abc attr_accessor :x end a = Abc.new a.instance_eval("@factor = 7") a.instance_eval("@x = 6 * @factor") puts a.x # напечатает 42 Час расплатыЗа такое удовольствие как замыкания, нужно платить.
Ссылки
КомментарииЧасто используемые элементы Textile, которые могут вам пригодиться при написании текста:
О дополнительных элементах можно прочитать тут: http://redcloth.org/textile
Войдите, чтобы оставить комментарий
|
artem.voroztsov
Был давно
Облако тегов
#rails
amazon web services
array
blocks
bootstrapping
closures
cloud computing
console
container
education
email
emerge
fiber
finders
gentoo
Getting Real
helper
hosting
JavaScript
jquery
lambda
lazy
liquid
metaprogramming
monkey patching
passenger
pipeline
plugin
proc
qsort
rails
rails 3
returning
ror
ruby
sass
serialize
snippets
tricks
tutorials
ubuntu
views
боевые искусства
вакансия
искусство
массив
мысли вслух
работа
Работа
фриланс
|
|||||||||||||||||||||||||||||||||||||||