Понимание Ruby Блоков, Проков и лямбда-выражений. | Participants
|
- Statistics
- Participants
- Translate into Russian
- Translation result
- 57% translated in draft.
If you do not want to register an account, you can sign in with OpenID.
Understanding Ruby Blocks, Procs and Lambdas | ||
Blocks, Procs and lambdas (referred to as closures in Computer Science) are one of the most powerful aspects of Ruby, and also one of the most misunderstood. This is probably because Ruby handles closures in a rather unique way. Making things more complicated is that Ruby has four different ways of using closures, each of which is a tad bit different, and sometimes nonsensical. There are quite a few sites with some very good information about how closures work within Ruby. But I have yet to find a good, definitive guide out there. Hopefully, this tutorial becomes just that. | Блоки, Проки и лямбда-выражения (так же называемые "замыканиями") -- одни из самых мощных возможностей языка Ruby, также и одни из самых сложных для правильного понимания, так как замыкания в ruby реализуются по-своему. Ruby поддерживает четыре (не всегда очевидных) пути создания замыканий. В Сети сложно найти хороший материал по этому вопросу. Надеюсь это руководство поможет вам разобраться с замыканиями в ruby. | |
First Up, Blocks | ||
The most common, easiest and arguably most “Ruby like” way to use closures in Ruby is with blocks. They have the following familiar syntax: | Самое частое, простое и наверное, наиболее полно соответствующее "Пути Ruby" -- использование замыканий с блоками. | |
array = [1, 2, 3, 4] puts array.inspect # => [1, 4, 9, 16] | array = [1, 2, 3, 4] array.collect! do |n| puts array.inspect # => [1, 4, 9, 16] | |
So, what is going on here? | ||
1. First, we send the collect! method to an Array with a block of code. | 1. Массиву "array" послали метод "collect!" с блоком кода. | |
2. The code block interacts with a variable used within the collect! method (n in this case) and squares it. | 2. В каждой итерации блок кода возводит в квадрат переменную метода "collect!" (в данном случае n). | |
3. Each element inside the array is now squared. | ||
Using a block with the collect! method is pretty easy, we just have to think that collect! will use the code provided within the block on each element in the array. However, what if we want to make our own collect! method? What will it look like? Well, lets build a method called iterate! and see. | Использовать блоки совместно с методом "collect!" очень легко -- мы просто должны понимать что метод "collect!" для каждой переменной массива выполняет код в блоке. Ну а что если мы захотим опрелелить собственный метод "collect!"? На что он будет похож? | |
class Array def iterate! array = [1, 2, 3, 4] array.iterate! do |n| puts array.inspect # => [1, 4, 9, 16] | class Array def iterate! self.each_with_index do |n, i| self[i] = yield(n) end array = [1, 2, 3, 4] array.iterate! do |n| puts array.inspect # => [1, 4, 9, 16] | |
To start off, we re-opened the Array class and put our iterate! method inside. We will keep with Ruby conventions and put a bang at the end, letting our users know to watch out, as this method might be dangerous! We then use our iterate! method just like Ruby’s built in collect! method. The neat stuff however, is right in the middle of our iterate! method definition. | Вначале мы добавили в класс "Array" метод "iterate!". Согласно принятым в ruby соглашением, мы поставили в конце названия метода восклицательный знак, чтобы предупредить о потенциальной опасности этого метода (он изменяет данные по месту, а не возвращает их). Далее мы воспользовались нашим методом также как и встроенным "collect!". Однако все интересное в середине определения метода. | |
Unlike attributes, you do not need to specify the name of blocks within your methods. Instead, you can use the yield keyword. Calling this keyword will execute the code within the block provided to the method. Also, notice how we are passing n (the integer that the each_with_index method is currently working with) to yield. The attributes passed to yield corresponds to the variable specified in the piped list of the block. That value is now available to the block and returned by the yield call. So to recap what is happening: | В отличие от атрибутов, вам не нужно указывать название блоков в своих методах. Вместо этого используется ключевое слово "yield". Использование этого ключевого слова приводит к выполнению кода внутри блока, переданного в метод. Обратите внимание как в yield передается n (целое, с которым сейчас работает метод each_with_index). Передаваемые в yield атрибуты соответствуют переменным в списке, ограниченным вертикальными чертами. Такое значение доступно блоку и возвращается вызовом yield. Резюмируем, что происходит: |
© Copyright © 2010 Robert Sosinski.
