Изучение Ruby: создание бесконечномерного массива с помощью блоковых атак - PullRequest
1 голос
/ 17 января 2011

Кто-нибудь, скажите мне, что здесь происходит:

a = [0,1,2]
a.each {|x| a[x] = a}

Результат - [[...], [...], [...]].И если я оцениваю a[0], я получаю [[...], [...], [...]].И если я оцениваю a[0][0], я получаю [[...], [...], [...]] до бесконечности.

Создал ли я массив бесконечной размерности?Как / почему это должно работать?

Ответы [ 2 ]

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

По сути, вы изменили каждый элемент в a для ссылки на сам список. Список рекурсивно ссылается на себя:

a[0] # => a
a[0][0] # => a[0], which is a
a[0][0][0] # => a[0][0], which is a[0], which is a
...

(# => - это рубин для "эта строка оценивается как")

В зависимости от того, как вы на это смотрите, оно не бесконечно. Это более или менее похоже на лист бумаги с надписью «Пожалуйста, переверните» с обеих сторон.

Причина, по которой Ruby печатает [...], заключается в том, что он достаточно умен, чтобы обнаружить, что список рекурсивен и позволяет избежать зацикливания.

Кстати, ваше использование each немного не идиоматично. each возвращает список, и вы обычно не присваиваете это возвращаемое значение переменной (поскольку у вас уже есть переменная, ссылающаяся на нее, a в данном случае). Другими словами, ваш код назначает [0,1,2] на a, затем переходит на a (устанавливает каждый элемент на a), затем присваивает a на a.

1 голос
/ 17 января 2011

Я думаю, что это само-ссылочная структура данных.A [x] = a помещает указатель a в [x].

...