заполнение ленивых последовательностей двоичных блоков
-
06-07-2019 - |
Вопрос
У меня есть функция Clojure, которая принимает последовательность чисел, разбивает ее на соответствующее количество битов и возвращает отложенную последовательность фрагментов (сначала биты младшего порядка).Он заполняет биты старшего порядка последнего блока, чтобы заполнить размер блока, и мне нужен совет о "наилучшем способе (tm)" записать объем заполнения, сохраняя его ленивым и функциональным?
Слова мудрости очень ценятся.
(defn block-seq ([block-size bytes] "reads a byte-seq into a sequence of block-size bits." (block-seq 8 block-size bytes)) ([in-block-size out-block-size bytes] "converts a seq from in-block-size to out-block-size" ...
Параметры:
- размер в блоке - это количество значащих битов в каждом числе во входной последовательности
- out-block-size - это количество значащих битов в каждом из возвращаемых чисел в lazy seq.
- байты - это ленивая последовательность чисел, из которой извлекаются биты
Вот пример, который берет последовательность из трех байт и разбивает ее на последовательность из двух двадцатибитных чисел (а затем выводит ее в виде двоичной строки).
user> (map #(java.lang.Integer/toBinaryString %) (block-seq 20 [0xAA 0xAA 0xAA])) ("10101010101010101010" "1010") user>
Второе число в последовательности из 20-битных чисел имеет только четыре значащих бита и имеет добавленные эффективные 16 нулей.Если бы я затем передал эту последовательность другой функции, которая хотела что-то сделать с последовательностью и отправить ее по сети;код на принимающей стороне должен знать, что не следует печатать / сохранять / etc последние 16 бит.
PS:они могут быть соединены цепочкой.(блок-seq 20 15 (блок-seq 8 20 (чтение байтов из файла)))
Решение
Все еще не совсем ясно, что вы хотите сделать, но, похоже, вы хотите знать наилучший способ для block-seq вернуть количество дополненных битов в последнем фрагменте.Конечно, это невозможно заранее, если вы хотите быть должным образом ленивым, поэтому число должно быть возвращено с последним фрагментом или после него.
Без использования метаданных вы могли бы просто вернуть список, подобный
(1 2 3 :pad 12)
Используя метаданные, вы могли бы добавить эту информацию о дополнении к последним минусам (Clojure не может добавлять метаданные к целым числам), поэтому последние минусы были бы эквивалентны
(with-meta '(3) {:pad 12})
Чтобы цепочка работала, binary-block должен был бы знать об этой информации о заполнении в обоих случаях, чтобы иметь возможность отменить заполнение, а затем повторно заполнить последний фрагмент.
Однако как передать информацию о заполнении по проводам - это другой вопрос.