Векторы
В схеме вектор — это еще одна фундаментальная структура данных, используемая для группировки значений. В отличие от списков, векторы представляют собой индексированные коллекции элементов фиксированного размера, обеспечивающие более быстрый произвольный доступ и обновления. Каждый элемент вектора может быть любого типа, включая другой вектор. Векторы обозначаются знаком #, за которым следуют круглые скобки. #(1 2 3)
Хотя векторы и списки могут показаться похожими, в программировании на Scheme они служат разным целям:
- Списки чаще используются для рекурсивных операций и динамических структур, поскольку их реализация со связанными узлами позволяет эффективно манипулировать их началом и обходом посредством рекурсивной декомпозиции.
С другой стороны, векторы оптимизированы для сценариев, в которых требуется произвольный доступ к элементам или обновления определенных индексов, что делает их более подходящими для таких случаев использования, как таблицы поиска, конфигурации фиксированного размера или индексированные операции, критичные к производительности.
По сути, списки являются естественным выбором для рекурсивных алгоритмов и данных динамического размера, в то время как векторы прекрасно подходят, когда первостепенное значение имеют шаблоны доступа фиксированного размера или индексированные.
Простые векторы
(vector 1 2 3)- Создает вектор из трех элементов:
1,2и3.
Результат: #(1 2 3)
Доступ к векторным элементам
Доступ к элементам вектора осуществляется с помощью процедуры vector-ref, она извлекает элемент по указанному индексу (начиная с 0).
(define my-vector (vector 1 2 3))
(vector-ref my-vector 0) ; Retrieves the element at index 0
(vector-ref my-vector 1) ; Retrieves the element at index 1Итерация: обработка каждого элемента вектора
Вы можете перебирать вектор, используя цикл или рекурсию. Схема предоставляет vector-length для определения размера вектора. Вот простой цикл для печати каждого элемента вектора:
(define (print-elements vec)
(let loop ((i 0))
(if (< i (vector-length vec))
(begin
(lumi-message (number->string (vector-ref vec i))) ; Print the element
(loop (+ i 1))) ; Process the next index
(lumi-message "done")))) ; End loop- Базовый случай: Если индекс
iдостигает длины вектора, остановите цикл. - Рекурсивный случай: Распечатайте элемент с индексом
i, затем увеличьтеi.
Пример использования
(print-elements (vector 1 2 3))Результат:
"1""2""3"
Результат: «готово»
Смешанные векторы
Векторы могут включать элементы разных типов, включая строки, логические значения, числа, другие векторы или даже результаты выражений:
(vector 42 "hello" #t (vector 1 2) (+ 3 4))Это создает вектор с:
- Номер (
42) - Строка (
"hello") - Логическое значение (
#t) - Другой вектор (
#(1 2)) - Результат выражения (
(+ 3 4), которое оценивается как7)
Результат: #(42 "hello" #t #(1 2) 7)
Построение векторов
Векторы создаются с помощью vector или с помощью make-vector для создания вектора фиксированного размера с начальным значением.
(make-vector 5 0)Создает вектор размера 5 со всеми элементами, инициализированными как 0.
Результат: #(0 0 0 0 0)
Обновление векторов
Процедура vector-set! обновляет элемент вектора по указанному индексу.
(define my-vector (vector 1 2 3))
(vector-set! my-vector 1 42) ; Sets the second element to 42
my-vectorРезультат: #(1 42 3)
Проверка векторов
Процедура vector? проверяет, является ли данное значение вектором.
(vector? (vector 1 2 3)) ; Checks if #(1 2 3) is a vector
(vector? 42) ; Checks if 42 is a vectorРезультат:
(vector? (vector 1 2 3))возвращает#t(истина)(vector? 42)возвращает#f(ложь)
Векторы и передача по ссылкеВ Scheme векторы изменяемы и передаются по ссылке. Это означает, что когда вы передаете вектор функции, функция может напрямую изменить исходный вектор. Любые изменения, внесенные в вектор внутри функции, будут отражены и за ее пределами. Такое поведение полезно для эффективного обмена и обновления данных в нескольких функциях, но оно также требует осторожности, чтобы избежать непредвиденных побочных эффектов.
Пример: изменение вектора в функции
Вот пример, демонстрирующий, как векторы передаются по ссылке и изменяются:
(define (modify-vector vec index new-value)
(vector-set! vec index new-value)) ; Updates the vector at the specified index
(define my-vector (vector 10 20 30))
(modify-vector my-vector 1 99) ; Modifies the second element to 99
my-vector ; The original vector is now updatedРезультат: #(10 99 30)
Пошаговое объяснение
- Создайте вектор:
my-vectorинициализируется значениями10,20и30. - Передача функции:
my-vectorпередаетсяmodify-vectorвместе с индексом и новым значением для обновления. - Изменить в функции: Процедура
vector-set!обновляет значение по указанному индексу непосредственно в исходном векторе. - Отражение изменений. Поскольку векторы передаются по ссылке, изменения, внесенные внутри функции, отражаются в исходном векторе.
Последствия передачи по ссылке
- Производительность. Передача векторов по ссылке эффективна, поскольку позволяет избежать копирования больших структур.
- Побочные эффекты: Будьте осторожны при совместном использовании векторов между функциями, чтобы избежать непреднамеренного изменения общих данных.
Операции с векторами
Scheme предоставляет несколько встроенных процедур для работы с векторами, в том числе:
vector-length: возвращает количество элементов в векторе.vector->list: преобразует вектор в список.list->vector: преобразует список в вектор.
(vector-length (vector 1 2 3)) ; Returns 3
(vector->list (vector 1 2 3)) ; Converts vector to list: (1 2 3)
(list->vector (list 1 2 3)) ; Converts list to vector: #(1 2 3)Результат:
(vector-length (vector 1 2 3))возвращает3(vector->list (vector 1 2 3))возвращает(1 2 3)(list->vector (list 1 2 3))возвращает#(1 2 3)
Вложенные векторы
Векторы в Scheme могут содержать другие векторы в качестве элементов, создавая вложенную структуру.
(define nested-vector (vector (vector 1 2) (vector 3 4) (vector 5)))Создает вектор из трех элементов, каждый из которых сам является вектором.
Результат: #(#(1 2) #(3 4) #(5))
Доступ к вложенным данным
Чтобы получить доступ к элементам внутри вложенного вектора, используйте vector-ref несколько раз для навигации по структуре.
Пример: доступ к элементам
(vector-ref nested-vector 0) ; Retrieves the first element: #(1 2)
(vector-ref (vector-ref nested-vector 0) 1) ; Retrieves the second element of the first vector: 2Резюме
- Векторы в Scheme представляют собой индексированные структуры данных фиксированного размера.
- Используйте
vectorдля создания вектора,vector-refдля доступа к элементам иvector-set!для обновления элементов. - Встроенные процедуры, такие как
vector-length,vector->listиlist->vector, обеспечивают гибкость операций. - Вложенные векторы позволяют создавать сложные иерархические структуры данных.