Как получить доступ к элементу в 2d массиве в Smalltalk - PullRequest
2 голосов
/ 11 марта 2020

Я начал программировать на Smalltalk и застрял здесь. У меня есть этот 2d массив:

testArr := Array new: 1.
testArr at: 1
    put: ((Array new: 3)
            at: 1 put: '1A';
            at: 2 put: '1B';
            at: 3 put: '1C';
            yourself).

Но если я хочу получить доступ, скажем, первый элемент первого массива, что я должен написать, чтобы это произошло?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 01 апреля 2020

У меня возникает соблазн воспользоваться вашим вопросом и ответом и немного рассказать о знаниях, относящихся к фольклору Smalltalk (о котором вы, возможно, уже знаете).

По мере того, как мы прогрессируем в использовании Smalltalk, мы, вероятно, заметим, что класс Array начинает играть уменьшающую роль в наших моделях. Это почему? Потому что требуется время, чтобы выяснить, какие объекты будут производить наши модели; баланс между слишком многими и слишком немногими является деликатным вопросом, в большинстве своем не знающим в начале.

Массивы и их состав представляют собой удобные структуры данных. Однако они решают проблему организации данных за счет борьбы с ними. Если клиенту такой структуры необходимо знать, как данные хранятся в качестве предварительного условия для действий с ними, то парадигма сообщения становится семантически бездействующей.

Давайте представим матричный объект. Есть несколько способов сохранить их записи: одномерный массив, массив строк, массив столбцов, словарь (разреженных) ненулевых записей, структура tri angular, если известно, что матрицы симметричны / антисимметричный / эрмитовой и многое другое для особых случаев. Конечно, это разнообразие не имеет смысла для рассматриваемой проблемы, и в любом случае было бы плохой идеей проводить время, рассматривая наиболее общий подход: В Smalltalk общность достигается в сообщении, а не в хранилище.

Независимо от внутренней организации данных, наши объекты всегда должны предлагать протоколы, которые не зависят от базовой структуры. Возвращаясь к примеру матрицы, даже если наша первоначальная организация представляет собой массив строк, объект матрицы должен работать одинаково, независимо от того, являются ли строки массивами или более сложными объектами vector , которые также используются для других целей. Это означает, что при кодировании внутреннего доступа к записи (i,j) мы должны делать вид, что не знаем класс строки i, а только сообщение для доступа к ее j -ому элементу. Что-то вроде

    atRow: i column: j
      | row |
      row := self row: i.
      ^row at: j

Здесь мы не предполагаем, что row является Array; мы только предполагаем, что он понимает сообщение at:, которое является наименьшим, что мы можем предположить при разговоре со строковым объектом, независимо от его фактической природы. Конечно, этот код хорош только в предположении, что строки не воссоздаются на лету, как если бы наш класс хранился вместо коллекций столбцов. Но это нормально, в противном случае нам нужно будет только добавить другой класс и переопределить этот и некоторые другие сообщения низкого уровня .

В любом случае, идея состоит в том, чтобы отложить как можно больше любые явные знания о внутренней организации, чтобы она ограничивалась несколькими личными сообщениями. Один из способов проверить, что мы применяем эту хорошую практику, - убедиться, что ни один код низкого уровня не повторяется в двух или более методах. Например, использование приведенного выше сообщения row: перемещает низкоуровневый код от atRow:column:, откладывая его на другой, который имеет смысл для (идеального) матричного протокола.

Этот пример иллюстрирует важный момент: с подозрением относиться к любому коду, который должен составлять два at: сообщения. И - почему бы не - насладиться красотой отсутствия необходимости объявлять типы.

1 голос
/ 11 марта 2020

Итак, проблема была в скобках.

^(testArr at: 1) at:1

возвращает

1A

по мере необходимости.

...