Объект № нажмите вопрос - PullRequest
0 голосов
/ 28 января 2011

Почему

a = [].tap do |x|
  x << 1
end
puts "a: #{a}"

работает как положено

a: [1]

, но

b = [].tap do |x|
  x = [1]
end
puts "b: #{b}"

не

b: []

?

Ответы [ 3 ]

3 голосов
/ 28 января 2011

Причина, по которой второй фрагмент не изменяет массив, та же самая, почему этот фрагмент:

def foo(x)
  x = [1]
end

a = []
foo(a)

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

Конечно, блоки также имеют замыкания на локальные переменные, в которых они были объявлены, так что это будет работать:

def foo(x)
  yield(x)
end

b = []
foo(123) do |x|
  b = [1]
end

p b # outputs [1]
0 голосов
/ 28 января 2011

Это немного не связано, но эта идиома [].tap ужасна.Вы не должны использовать это.Даже многие люди, которые использовали его в коде rails, теперь признают, что это ужасно, и больше не используют его.

Не используйте его.

0 голосов
/ 28 января 2011

Первый метод помещает 1 в конец пустого массива.Точно так же вы не можете сказать, что пустой массив равен 1. Скорее вы попытаетесь скопировать его ...

b = [].tap do |x|
   x.unshift(1)
end

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

Array.methods.sort

Всего наилучшего и удачи

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...