Понимание Ruby Блоков, Проков и лямбда-выражений.

Robert Sosinski, “Understanding Ruby Blocks, Procs and Lambdas”, public translation into Russian from English More about this translation.

See also 109 similar translations

Translate into another language.

Participants

alexbaumgertner818 points
and_rew283 points
deeper4k138 points
And others...
Join Translated.by to translate! If you already have a Translated.by account, please sign in.
If you do not want to register an account, you can sign in with OpenID.
Pages: ← previous Ctrl next next untranslated
1 2 3 4 5 6

Understanding Ruby Blocks, Procs and Lambdas

Понимание Ruby Блоков, Проков и лямбда-выражений.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

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.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

First Up, Blocks

Начнем с Блоков

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

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" -- использование замыканий с блоками.
Знакомый вам синтаксис:

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

array = [1, 2, 3, 4]
array.collect! do |n|
n ** 2
end

puts array.inspect # => [1, 4, 9, 16]

array = [1, 2, 3, 4]

array.collect! do |n|
n ** 2
end

puts array.inspect # => [1, 4, 9, 16]

History of edits (Latest: and_rew 1 year, 7 months ago) §

So, what is going on here?

Что мы сделали?

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

1. First, we send the collect! method to an Array with a block of code.

1. Массиву "array" послали метод "collect!" с блоком кода.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

2. The code block interacts with a variable used within the collect! method (n in this case) and squares it.

2. В каждой итерации блок кода возводит в квадрат переменную метода "collect!" (в данном случае n).

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

3. Each element inside the array is now squared.

3. Все элементы массива возведены в квадрат.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

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!"? На что он будет похож?
Давайте создадим метод "iterate!" и посмотрим.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

class Array

def iterate!
self.each_with_index do |n, i
self[i] = yield(n)
end
end
end

array = [1, 2, 3, 4]

array.iterate! do |n|
n ** 2
end

puts array.inspect # => [1, 4, 9, 16]

class Array

def iterate!

self.each_with_index do |n, i|

self[i] = yield(n)
#для элемента массива (n) по индексу "объект[i]" выполнить блок кода "yield"

end
end
end

array = [1, 2, 3, 4]

array.iterate! do |n|
n ** 2
end

puts array.inspect # => [1, 4, 9, 16]

History of edits (Latest: and_rew 1 year, 7 months ago) §

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!". Однако все интересное в середине определения метода.

History of edits (Latest: alexbaumgertner 1 year, 7 months ago) §

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. Резюмируем, что происходит:

History of edits (Latest: and_rew 1 year, 7 months ago) §
Pages: ← previous Ctrl next next untranslated
1 2 3 4 5 6

© Copyright © 2010 Robert Sosinski.