Spec-Zone.ru › OCaml 4.14

Модуль Hashtbl

module Hashtbl: sig .. end

Хэш-таблицы и хэш-функции.

Хэш-таблицы — это хешированные ассоциативные таблицы с модификациями на месте.

Общий интерфейс

type ('a, 'b) t 

Тип хэш-таблиц от типа 'a до типа 'b.

val create : ?random:bool -> int -> ('a, 'b) t

Hashtbl.create n создаёт новую пустую хэш-таблицу с начальным размером n. Для достижения наилучших результатов, n должен быть порядка ожидаемого количества элементов, которые будут в таблице. Таблица увеличивается по мере необходимости, поэтому n — это лишь первоначальная оценка.

Необязательный параметр ~random (булево значение) управляет тем, является ли внутренняя организация хэш-таблицы случайной при каждом выполнении Hashtbl.create или детерминированной во всех выполнениях.

Хэш-таблица, созданная с параметром ~random установленным в значение false, использует фиксированную хэш-функцию (Hashtbl.hash) для распределения ключей по корзинам. Вследствие этого коллизии между ключами происходят детерминированно. В приложениях, ориентированных на веб, или в других приложениях, чувствительных к безопасности, детерминированные шаблоны коллизий могут быть использованы злоумышленником для создания атаки с отказом в обслуживании: злоумышленник отправляет входные данные, специально составленные для создания множества коллизий в таблице, замедляя работу приложения.

Хэш-таблица, созданная с параметром ~random установленным в значение true, использует семенную хэш-функцию Hashtbl.seeded_hash с семенем, случайным образом выбранным во время создания хэш-таблицы. По сути, используемая хэш-функция выбирается случайным образом среди 2^{30} различных хэш-функций. Все эти хэш-функции имеют разные шаблоны коллизий, что делает неэффективной атаку с отказом в обслуживании, описанную выше. Однако из-за случайности перечисление всех элементов хэш-таблицы с помощью Hashtbl.fold или Hashtbl.iter больше не является детерминированным: элементы перечисляются в разных порядках при разных запусках программы.

Если параметр ~random не указан, хэш-таблицы создаются по умолчанию в неслучайном режиме. Этот параметр по умолчанию можно изменить либо программно, вызвав Hashtbl.randomize, либо установив флаг R в переменной окружения OCAMLRUNPARAM.

  • До версии 4.00.0 параметр ~random отсутствовал, и все хэш-таблицы создавались в нерандомизированном режиме.
val clear : ('a, 'b) t -> unit

Очистить хэш-таблицу. Используйте reset вместо clear, чтобы уменьшить размер таблицы корзин до её начального размера.

val reset : ('a, 'b) t -> unit

Очистить хэш-таблицу и уменьшить размер таблицы корзин до её начального размера.

  • С версии 4.00.0
val copy : ('a, 'b) t -> ('a, 'b) t

Возвращает копию заданной хэш-таблицы.

val add : ('a, 'b) t -> 'a -> 'b -> unit

Hashtbl.add tbl key data добавляет связывание key с data в таблице tbl. Предыдущие связывания для key не удаляются, а просто скрываются. То есть, после выполнения Hashtbl.remove tbl key, предыдущее связывание для key, если оно было, восстанавливается. (Такое же поведение, как и с ассоциативными списками.)

val find : ('a, 'b) t -> 'a -> 'b

Hashtbl.find tbl x возвращает текущее связывание x в tbl, или вызывает исключение Not_found, если такого связывания не существует.

val find_opt : ('a, 'b) t -> 'a -> 'b option

Hashtbl.find_opt tbl x возвращает текущее связывание x в tbl, или None, если такого связывания не существует.

  • С версии 4.05
val find_all : ('a, 'b) t -> 'a -> 'b list

Hashtbl.find_all tbl x возвращает список всех данных, связанных с x в tbl. Текущая привязка возвращается первой, затем предыдущие привязки в обратном порядке их ввода в таблицу.

val mem : ('a, 'b) t -> 'a -> bool

Hashtbl.mem tbl x проверяет, привязана ли x в tbl.

val remove : ('a, 'b) t -> 'a -> unit

Hashtbl.remove tbl x удаляет текущую привязку x в tbl, восстанавливая предыдущую привязку, если она существует. Если x не привязана в tbl, она ничего не делает.

val replace : ('a, 'b) t -> 'a -> 'b -> unit

Hashtbl.replace tbl key data заменяет текущую привязку key в tbl привязкой key к data. Если key не привязана в tbl, к tbl добавляется привязка key к data. Это функционально эквивалентно Hashtbl.remove tbl key за которым следует Hashtbl.add tbl key data.

val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit

Hashtbl.iter f tbl применяет f ко всем привязанностям в таблице tbl. f получает ключ в качестве первого аргумента, а связанное значение — как второй аргумент. Каждая привязка представляется точно один раз для f.

Порядок, в котором привязки передаются f, не определён. Однако, если таблица содержит несколько привязок к одному ключу, они передаются f в обратном порядке ввода, то есть самая последняя привязка передаётся первой.

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

Поведение не определено, если хеш-таблица модифицируется f во время итерации.

val filter_map_inplace : ('a -> 'b -> 'b option) -> ('a, 'b) t -> unit

Hashtbl.filter_map_inplace f tbl применяет f ко всем привязанностям в таблице tbl и обновляет каждую привязку в зависимости от результата f. Если f возвращает None, привязка удаляется. Если возвращает Some new_val, привязка обновляется, связывая ключ со значением new_val.

Другие комментарии для Hashtbl.iter также применимы.

  • Since 4.03.0
val fold : ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c

Hashtbl.fold f tbl init вычисляет (f kN dN ... (f k1 d1 init)...), где k1 ... kN — ключи всех привязанностей в tbl, а d1 ... dN — связанные значения. Каждая привязка представляется ровно один раз для f.

Порядок, в котором привязки передаются f, не определён. Однако, если таблица содержит несколько привязок к одному ключу, они передаются f в обратном порядке ввода, то есть самая последняя привязка передаётся первой.

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

Поведение не определено, если хеш-таблица модифицируется f во время итерации.

val length : ('a, 'b) t -> int

Hashtbl.length tbl возвращает количество привязок в tbl. Она занимает постоянное время. Несколько привязок считаются по одному разу, поэтому Hashtbl.length даёт количество раз, когда Hashtbl.iter вызывает свой первый аргумент.

val randomize : unit -> unit

После вызова Hashtbl.randomize(), хеш-таблицы по умолчанию создаются в режиме рандомизации: Hashtbl.create возвращает рандомизированные хеш-таблицы, если не задан необязательный параметр ~random:false. То же самое можно сделать, установив параметр R в переменной среды OCAMLRUNPARAM.

Рекомендуется, чтобы приложения или веб-фреймворки, которым нужно защитить себя от атаки с отказом в обслуживании, описанной в Hashtbl.create, вызывали Hashtbl.randomize() во время инициализации.

Обратите внимание, что после вызова Hashtbl.randomize(), нет способа вернуться к поведению по умолчанию Hashtbl.create без рандомизации. Это сделано намеренно. Хеш-таблицы без рандомизации всё ещё можно создать, используя Hashtbl.create ~random:false.

  • Since 4.00.0
val is_randomized : unit -> bool

Возвращает true, если таблицы по умолчанию создаются в режиме рандомизации, false в противном случае.

  • Since 4.03.0
val rebuild : ?random:bool -> ('a, 'b) t -> ('a, 'b) t

Возвращает копию заданной хеш-таблицы. В отличие от Hashtbl.copy, Hashtbl.rebuild h перехеширует все пары (ключ, значение) исходной таблицы h. Возвращённая хеш-таблица будет случайной, если h была случайной, или необязательный параметр random имеет значение true, или если по умолчанию создаются случайные хеш-таблицы; см. Hashtbl.create для получения дополнительной информации.

Hashtbl.rebuild может безопасно использоваться для импорта хеш-таблицы, созданной старой версией модуля Hashtbl, а затем сериализованной в постоянное хранилище. После десериализации примените Hashtbl.rebuild для получения хеш-таблицы для текущей версии модуля Hashtbl.

  • Since 4.12.0
type statistics = {
num_bindings : int; (*

Число пар ключ-значение в таблице. Соответствует значению, возвращаемому функцией Hashtbl.length.

*)
num_buckets : int; (*

Количество бакетов в таблице.

*)
max_bucket_length : int; (*

Максимальное количество пар ключ-значение в бакете.

*)
bucket_histogram : int array; (*

Гистограмма размеров бакетов. Этот массив histo имеет длину max_bucket_length + 1. Значение histo.(i) равно числу бакетов, размер которых равен i.

*)
}
  • Since 4.00.0
val stats : ('a, 'b) t -> statistics

Hashtbl.stats tbl возвращает статистику о таблице tbl: количество бакетов, размер самого большого бакета, распределение бакетов по размеру.

  • Since 4.00.0

Хеш-таблицы и последовательности

val to_seq : ('a, 'b) t -> ('a * 'b) Seq.t

Итерирование по всей таблице. Порядок, в котором пары ключ-значение появляются в последовательности, не определён. Однако, если таблица содержит несколько пар с одинаковым ключом, они появляются в обратном порядке добавления, то есть самая последняя пара появляется первой.

Поведение не определено, если хеш-таблица изменяется во время итерации.

  • Since 4.07
val to_seq_keys : ('a, 'b) t -> 'a Seq.t

То же, что и Seq.map fst (to_seq m)

  • Since 4.07
val to_seq_values : ('a, 'b) t -> 'b Seq.t

То же, что и Seq.map snd (to_seq m)

  • Since 4.07
val add_seq : ('a, 'b) t -> ('a * 'b) Seq.t -> unit

Добавление заданных пар ключ-значение в таблицу, используя Hashtbl.add

  • Since 4.07
val replace_seq : ('a, 'b) t -> ('a * 'b) Seq.t -> unit

Добавление заданных пар ключ-значение в таблицу, используя Hashtbl.replace

  • Since 4.07
val of_seq : ('a * 'b) Seq.t -> ('a, 'b) t

Создание таблицы из заданных пар ключ-значение. Пары добавляются в том же порядке, в котором они появляются в последовательности, используя Hashtbl.replace_seq, что означает, что если две пары имеют одинаковый ключ, то в таблице будет только последняя.

  • Since 4.07

Функциональный интерфейс

Функциональный интерфейс позволяет использовать специфические функции сравнения и хеширования, либо для повышения производительности/безопасности, либо потому что ключи не хешируются/сравниваются встроенными полиморфными функциями.

Например, можно специализировать таблицу для целочисленных ключей:

      module IntHash =
        struct
          type t = int
          let equal i j = i=j
          let hash i = i land max_int
        end

      module IntHashtbl = Hashtbl.Make(IntHash)

      let h = IntHashtbl.create 17 in
      IntHashtbl.add h 12 "hello"
    

Это создаёт новый модуль IntHashtbl, с новым типом 'a
    IntHashtbl.t
таблиц от int до 'a. В данном примере, h содержит string значения, поэтому её тип string IntHashtbl.t.

Обратите внимание, что новый тип 'a IntHashtbl.t не совместим с типом ('a,'b) Hashtbl.t общего интерфейса. Например, Hashtbl.length h не будет проверяться, нужно использовать IntHashtbl.length.

module type HashedType = sig .. end

Входная сигнатура функтора Hashtbl.Make.

module type S = sig .. end

Выходная сигнатура функтора Hashtbl.Make.

module Make: functor (H : HashedType) -> S  with type key = H.t

Функтор, строящий реализацию структуры хеш-таблицы.

module type SeededHashedType = sig .. end

Входная сигнатура функтора Hashtbl.MakeSeeded.

module type SeededS = sig .. end

Выходная сигнатура функтора Hashtbl.MakeSeeded.

module MakeSeeded: functor (H : SeededHashedType) -> SeededS  with type key = H.t

Функтор, строящий реализацию структуры хеш-таблицы.

Полиморфные функции хеширования

val hash : 'a -> int

Hashtbl.hash x сопоставляет неотрицательное целое число любому значению любого типа. Гарантируется, что если x = y или Stdlib.compare x y = 0, то hash x = hash y. Более того, hash всегда завершается, даже на циклических структурах.

val seeded_hash : int -> 'a -> int

Вариант Hashtbl.hash, дополнительно параметризованный целочисленным зерном.

  • Since 4.00.0
val hash_param : int -> int -> 'a -> int

Hashtbl.hash_param meaningful total x вычисляет значение хеша для x, с теми же свойствами, что и для hash. Два дополнительных целочисленных параметра meaningful и total предоставляют более точный контроль над хешированием. Хеширование выполняет обход структуры x по принципу «ширина в глубину», слева направо, останавливаясь после того, как было встречено meaningful значимых узлов или total узлов (значимых или нет). Если total (заданное пользователем) превышает определённое значение, в настоящее время 256, то оно ограничено этим значением. Значимые узлы: целые числа; числа с плавающей точкой; строки; символы; булевы значения; и константные конструкторы. Большие значения meaningful и total означают, что для вычисления конечного значения хеша учитывается больше узлов, а значит вероятность коллизий меньше. Однако хеширование занимает больше времени. Параметры meaningful и total регулируют компромисс между точностью и скоростью. В качестве значений по умолчанию, Hashtbl.hash и Hashtbl.seeded_hash принимают meaningful = 10 и total = 100.

val seeded_hash_param : int -> int -> int -> 'a -> int

Вариант Hashtbl.hash_param, дополнительно параметризованный целочисленным зерном. Использование: Hashtbl.seeded_hash_param meaningful total seed x.

  • Since 4.00.0

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/4.14/htmlman/libref/Hashtbl.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API