Procs from Understanding Ruby Blocks, Procs и Lambdas Статья

Хорошо, просматриваю процедуры, лямбда-выражения и блоки через этот block-procs-and-lambdas/" rel="nofollow">ссылка.

Вопрос по этому коду:

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

Концептуально я понимаю почти все, кроме одной строчки, а именно:

self[i] = yield(n)

Я так понимаю, это self в этой строке self.each_with_index do |n, i| означает, что это метод класса, верно?

Но зачем нам назначать параметры в yield(n) для self[i]?

Пожалуйста, объясните супер простым способом, если можете.

(другими словами, пожалуйста, будьте любезны, как и большинство людей здесь, просто немного нервничайте из-за того, что я не понимаю, что заставляет меня чувствовать себя глупо)


person user273072545345    schedule 28.10.2014    source источник


Ответы (5)


Это метод iterate!, который является методом экземпляра. self в self.each_with_index является получателем метода Enumerable#each_with_instance. Поскольку self является текущим экземпляром Array (в вашем примере [1,2,3,4]), self. не требуется; т. е. вы могли бы (и, по моему мнению, должны) просто написать each_with_index do |n, i|.... Другими словами, self является подразумеваемым получателем, если явный получатель не указан.

Относительно линии:

self[i] = yield(n)

для вашего примера array = [1,2,3,4] ваш перечислитель:

enum = [1,2,3,4].each_with_index
  #=> #<Enumerator: [1, 2, 3, 4]:each_with_index>

с элементами

enum.to_a
  #=> [[1, 0], [2, 1], [3, 2], [4, 3]]

Таким образом, первый элемент, переданный в блок с помощью Array#each, — это [1,0], который присваивается переменным блока:

n = 1
i = 0

в результате чего

self[0] = yield(1) => 1**2 => 1

и так далее.

person Cary Swoveland    schedule 28.10.2014

Я постараюсь объяснить супер простым способом.

Я так понимаю, это self в этой строке self.each_with_index do |n, i| означает, что это метод класса, верно?

Неа. Значение self зависит от контекста. Если бы self было в классе, оно бы относилось к классу. Но здесь self находится в методе экземпляра, поэтому он ссылается на экземпляр (поэтому each_with_index также является методом экземпляра).

Но зачем нам назначать параметры в yield(n) для self[i]?

Целью iterate! является изменение массива на месте. Поскольку self относится к экземпляру, self[i] обращается к элементам массива, к которому вызывается iterate!, тем самым изменяя массив на месте.

Кроме того, я не уверен, что вы подразумеваете под «параметрами» здесь. yield(n) передает n блоку, запускает блок и возвращает значение.

person Max    schedule 28.10.2014

self[i] = yield(n) переназначает значения в массиве блоку, указанному в

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

что в основном означает, возьмите значение массива и возведите его в квадрат, сохраните это значение в элементе массива. Итак, [1, 2, 3 , 4] становится [1 ** 2, 2 ** 2, 3 ** 2, 4 ** 2] => [2, 4, 9, 16]

person SuckerForMayhem    schedule 28.10.2014

Self изменяется (и фактически является) текущим контекстом или окружающим объектом.

С

self.each_with_index do |n, i|
...

это обезьяна, исправляющая класс Array и находящаяся внутри метода экземпляра iterate!, self ссылается на сам экземпляр: в данном случае массив [1, 2, 3, 4].

Вы, наверное, думаете об этом:

class some_class

  def self.a_class_method
  ...

который определен в контексте класса. Таким образом, self - это сам класс (который также является объектом), а не экземпляр этого класса.

Поскольку self - это просто массив [1, 2, 3, 4]

self[i] = yield(n)

заменяет каждый элемент массива результатами отправленного блока.

person seph    schedule 28.10.2014

Вот повторяй! является функцией экземпляра класса Array, и у вас есть объект массива. Когда вы делаете

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

Вы проходите блок 'do |n| N ** 2 конец для итерации! function. В функции вы можете получить доступ к этому блоку, используя yield. Но, как вы можете видеть, блок ожидает один параметр через |n| поэтому вам нужно передать один параметр, и код блока вернет его квадрат.

self[i] = yield(n)

self используется в контексте экземпляра массива. Таким образом, он изменяет значения массива.

Для получения дополнительной информации, пожалуйста, проверьте эту статью:

http://geekdirt.com/blog/blocks-lambda-and-procs-in-ruby/

person Shobhit_Geek    schedule 05.08.2015