Ссылка на массив в Ruby?
Могу ли я иметь ссылку на ячейку массива в Ruby? В C++ я могу сделать что-то вроде:
int& ref = arr[x][y];
а потом работать с переменной ref
без необходимости печатать весь arr[x][y]
,
Я хочу сделать это, так как мне нужно обращаться к одной и той же ячейке несколько раз в функции (я делаю заметки), и ввод ненужных индексов может привести только к ошибкам.
4 ответа
Все значения в ruby являются ссылками, так что это, безусловно, возможно, но с некоторыми важными ограничениями. Единственное предостережение в том, что ruby НЕ ПРЯМО поддерживает многомерные массивы, но вы можете реализовать его как массив массивов или как хеш-код с ключами от кортежей.
Этого можно добиться в тех случаях, когда значение в (x, y) уже было установлено путем присвоения значения в заданных координатах. Если в этом месте в настоящее время нет значения, то вы должны инициализировать это значение, прежде чем сможете иметь ссылку на него:
# if x and y are indices and a is your "multidimensional array"
a[x][y] = 'First Value' # Initial value at (x, y)
ref = a[x][y] # take a reference to the value referenced by a[x][y]
ref.gsub! 'First', 'Second'
a[x][y] # => 'Second Value'
Имейте в виду, что оператор присваивания в ruby обычно означает "сделать ссылку на левую сторону ссылкой на значение справа". Это означает, что если вы используете оператор присваивания в вашей ссылке, то вы фактически заставляете его ссылаться на новое значение:
a[x][y] = 1 # Initialize value with 1
ref = a[x][y] # Take the reference
ref += 1 # Assignment
ref # => 2
a[x][y] # => 1
Вы могли бы добиться большего успеха, используя Hash
и вводить хеш с кортежами ваших координат, а затем использовать эти кортежи для получения ссылок на определенные местоположения:
a = {}
loc = [x, y]
a[loc] = 'First Value' # Initial value
a[[x,y]] # => 'First Value'
a[loc] = 'Second Value' # Assignment
a[[x,y]] # => 'Second Value'
a[loc] = 1 # Assignment
a[loc] += 1 # Assignment
a[[x,y]] # => '2'
В языке высокого уровня, таком как ruby, все переменные являются ссылками, и нет никаких "указателей" или уровней косвенных указаний, таких как C или C++, вы должны создать объекты для хранения этих ссылок, чтобы получить похожее поведение
Это то, что я бы сделал на ruby
Предположим, вам нужно сохранить "указатель" на массив ruby, а затем создать класс для доступа к массиву в заданном индексе (нет такой вещи, как получение "указателя" на значение в ruby).
class ArrayPointer
def initialize(array, index)
@array = array
@index = index
end
def read
@array[index]
end
def write(value)
@array[index] = value
end
end
Затем вы используете фразу таким образом
array = [1, 2, 3]
pointer = ArrayPointer.new(array, 1)
pointer.write(20)
puts array # [1, 20, 3]
Вы также можете получить "указатели" на локальные переменные, но это слишком странно и необычно в мире ruby, и это почти не имеет смысла
Обратите внимание, что этот вид кода странный и не распространенный в ruby, но с дидактической точки зрения интересно сравнить два замечательных языка, таких как Ruby и C
В объектно-ориентированной природе ruby предпочтительно проектировать хорошие абстракции (например, вместо использования массива для представления ваших данных, если предпочтительнее определить класс с помощью методов, таких как метод ruby), прежде чем использовать только элементарные структуры, такие как Array или Hash для представлять данные, используемые вашей программой (последний подход, распространенный в C, это не метод ruby)
Чтобы ref продолжал указывать на фактические данные arr[x][y] в любой момент времени, можно написать его как метод:
def ref
ar[1][1]
end
Ruby считается проходным по значению, поэтому, чтобы ответить на ваш вопрос (не передаваемый по ссылке, как C++), напрямую выполнить то, что вы просите, невозможно.
В этом ответе Эйба есть действительно хороший пост, который вы должны прочитать: