Непостижимый Рубин: Пример назначения вектора - PullRequest
7 голосов
/ 28 января 2011

Рассмотрим следующее:

a=[0,1] #our starting value
a=[a,1] #=> [[0,1],1] as expected

Я ожидал бы, что следующий результат будет таким же:

a=[0,1] #same starting place
a[0]=a  #should make a the same thing as it was above, right?
a       #=> [[...],1]   !!!

В первом примере второе назначение относится к значению a до того, как назначение было выполнено. Во втором примере второе назначение выполняет рекурсивное назначение. Это похоже на другое поведение для меня. Является ли это поведение на самом деле последовательным? Если да, то может кто-нибудь объяснить, почему?

Ответы [ 2 ]

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

В первом примере вы создаете новый массив со значением [[0,1], 1]. Затем вы переназначаете a для обращения к этому массиву.

Во втором примере вы не создаете новый массив и не меняете то, к чему относится a. Вы изменяете существующий массив , чтобы он содержал ссылку на себя. Это совсем другое.


Подробнее

Первый пример примерно эквивалентен этому коду:

a = [0, 1]  # Step 1
b = [a, 1]  # Step 2
a = b       # Step 3

На картинках это выглядит так:

  • Шаг 1 - создать массив:
---
|a|
---
 |
 v
 [0, 1]
  • Шаг 2 - создайте еще один массив, который включает ссылку на первый:
    ---        ---
    |a|        |b| 
    ---        ---
     |          |
     |          v
     |          [ref, 1]
     |            |
     +------------+
     v 
     [0, 1]      
  • Шаг 3 - измените a так, чтобы он указывал на массив, созданный на шаге 2:
    ---        ---
    |a|        |b| 
    ---        ---
     |          |
     +----------+
                v
                [ref, 1]
                  |
    +-------------+
    v 
    [0, 1]      

С другой стороны, код во втором примере дает вам следующее:

    ---
    |a|
    ---
     |
 +---+
 |   v
 |   [ref, 1]
 |     |
 +-----+

Здесь все еще только один массив, и a все еще указывает на него. Но теперь первый элемент в массиве относится к самому массиву.

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

В ruby ​​все переменные (без исключений) являются ссылками.

В этом случае a является ссылкой на массив.Вроде как a в int *a в C.

Делая a[0] = a, вы создаете a массив, где первый элемент является ссылкой на a.

...