LINUX.ORG.RU

Ruby & окружения/область видимости


0

0

Только что обнаружил вот такое поведение, которое мне кажется 
интересным/нелогичным/неочевидным. 

irb(main):001:0> x = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> x.map {|x| x + 1}
=> [2, 3, 4, 5, 6]
irb(main):003:0> x
=> 5

Хотя судя по всему еще все поменяется.

http://redhanded.hobix.com/inspect/ruby20BlockLocalVariable.html
http://redhanded.hobix.com/inspect/blockAndLambda.html
★★★★★
Ответ на: комментарий от Zmacs

Ну так какая разница. Например в Python
In [7]: x = [1,2,3,4,5]
In [8]: map(lambda x: x + 1, x)
Out[8]: [2, 3, 4, 5, 6]
In [9]: x
Out[9]: [1, 2, 3, 4, 5]
Я не говорю, что такое поведение единственно верное. Тем не менее 
если все же значение, на которое ссылается внешний x, меняется, то 
почему тогда map все равно возвращает [2,3,4,5,6] ?

grob ★★★★★
() автор топика

Такое поведение конечно неправильно. А всё из-за того, что переменная является локальной для блока только если она не была ранее объявлена во включающей области действия. То есть надо быть осторожнее с именами переменных блока. Зачем Матц так сделал непонятно. Но в 2.0 это точно исправят.

anonymous
()
Ответ на: комментарий от grob

> Тем не менее если все же значение, на которое ссылается внешний x,
меняется, то почему тогда map все равно возвращает [2,3,4,5,6]

Объект, на который ссылается внешний x, не изменяется. Он лишь
получает сообщение map через x, а потом использует уже своё внутреннее 
состояние. Просто блок при первом вызове переводит указатель x с
одного объекта (массива) на другой, который ему передаёт map. Сам 
исходный массив не изменяется, но ссылок на него уже нет, x ссылается 
на другой объект. Такое поведение является ошибочным, иных мнений быть 
не может.

На примере:
irb(main):001:0> x = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> y = x
=> [1, 2, 3, 4, 5]
irb(main):003:0> x.object_id
=> -605527620
irb(main):004:0> y.object_id
=> -605527620
irb(main):005:0> x.map {|x| x+1}
=> [2, 3, 4, 5, 6]
irb(main):006:0> x
=> 5
irb(main):007:0> x.object_id
=> 11
irb(main):008:0> y
=> [1, 2, 3, 4, 5]

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.