На главную Назад Вперёд

Массивы

Локальные обозначения

Использование define для введения новых обозначений не всегда удобно. Часто возникает необходимость введения обозначений, действующих только внутри некоторого выражения. Для этого используется специальная форма let:

(let список_обозначений выражение_1 выражение_2 ... выражение_n)

список обозначений = [(название_1 значение_1) (название_2 значение_2) ... (название_m значение_m)]

Эта форма вычисляет по очереди выражение_1, выражение_2, и т.д., в рамках которых допустимо использовать введённые обозначения. Значением всей формы является значение последнего выражения в ней. Напоминаем, что квадратные скобки стоят только для повышения читаемости (и поддерживаются, к сожалению, не всеми реализациями языка Scheme).

Пример использования:

(define (print-sum)
  (display "Введите пару чисел: ")
  
  (let [(a (read))
        (b (read))]
    (display a) (display " + ") (display b) (display " = ") (display (+ a b))
    (newline)))

Массивы

Массивом называется способ хранения данных, обладающий следующими особенностями:

  1. каждой единице данных сопоставляется номер из некоторого непрерывного диапазона целых чисел;

  2. по этому номеру можно «быстро» получать доступ к единице данных с этим номером.

Под «быстро» понимается, что время доступа (в некотором приближении) не зависит от количества хранимых данных (или от порядкового номера).

Традиционные списки в языке Scheme обладают первым свойством (каждому элементу можно сопоставить порядковый номер), но не обладают вторым: для того, чтобы получить доступ, например, к последнему элементу, нужно пройти весь список с начала до конца.

Массивы в Scheme называются словом vector. Создать массив можно одним из двух способов:

(make-vector длина начальное_значение)      ;; задав форму 
(vector элемент_1 элемент_2 ... элемент_n)  ;; задав элементы

Нумерация элементов массива начинается с нуля. Узнать количество хранимых элементов можно функцией vector-length. Обратиться к указанному элементу можно так:

(vector-ref  вектор номер)           ;; получение текущего значения
(vector-set! вектор номер значение)  ;; сохранение в вектор заданного значения

Упражнения

  1. Напишите функцию vector-copy, возвращающую копию поданного ей на вход массива.

  2. Напишите функцию vector-resize, создающую новый массив заданного размера, начало которого совпадает с началом указанного массива:

(vector-resize (vector 1 2 3) 2)  ;; новый вектор: #(1 2)
(vector-resize (vector 1 2 3) 4)  ;; новый вектор: #(1 2 3 что-угодно)
  1. Напишите функцию vector-maximum, находящую максимальное число в массиве.

  2. Напишите функцию vector-map, применяющую заданную функцию к каждому элементу массива и создающую новый массив из этих значений.

  3. Напишите функцию vector-map!, заменяющую каждый элемент массива на результат применения к нему заданной функции.

  4. Напишите функцию vector-reduce, осуществляющую левую свёртку массива (ту, что foldl).

  5. Напишите функцию make-grid, создающую «двухмерный массив» указанных размеров. Реализуйте следующие операции:

(grid-width  g)     ;; первое измерение массива g
(grid-height g)     ;; второе измерение массива g
(grid-ref g i j)    ;; элемент массива g с координатами i,j
(grid-set! g i j x) ;; сохранение в элемент массива g с координатами i,j значения x

Для реализации двухмерного массива вы можете использовать как «массив массивов», так и одномерный массив с пересчётом координат.

@ 2016 arbrk1, all rights reversed