Общий Lisp: получение всех ключей данной хэш-таблицы в виде списка
Интересно, существует ли менее вербальный способ, чем использование цикла. В любом случае это работает для меня в CLISP:
(loop for key being the hash-keys of *my-hash* collect key)
Я видел других, использующих maphash
, но это связано с накоплением каждого ключа в списке. Помимо того, что это более активное участие, чем использование цикла, он также вводит побочный эффект, который я стараюсь избегать, когда только могу - я предпочитаю функциональное программирование как можно больше:)
Есть ли что-либо предопределенное для этой общей задачи, даже если оно специфично для реализации?
(defun hash-keys (hash-table)
(loop for key being the hash-keys of hash-table collect key))
Ответы
Ответ 1
Общий Lisp исходит из того, что философия стала более распространенной, и большинство функций, как ожидается, будут предоставляться сторонними библиотеками, а не реализациями. В то время как Common Lisp иногда называют большим языком, он сравнивается только с C и аналогичным, сам язык довольно крошечный по сравнению с Python и другими языками с массивными стандартными библиотеками.
Для этой конкретной цели Alexandria является обычно используемой коллекцией общих Lisp утилит. Среди многих других вещей он содержит hash-table-keys
.
Ответ 2
Нет недостатка в определении
(defun hash-keys (hash-table)
(loop for key being the hash-keys of hash-table collect key))
потому что в Common Lisp функция скомпилирована. Если ваш поставщик предоставил эту функцию, он в значительной степени сделает то же самое и не будет намного более эффективным, чем ваш, если вообще.
В интерпретируемых языках почти все, что вы пишете, имеет недостаток производительности по сравнению с "внутренней" процедурой.
Консолидация содержимого хэша расточительна; loop позволяет обрабатывать хеш без сохранения памяти. Так что, возможно, вам нужен макрос (некоторые Lisps предоставляют dohash
или похожий как расширение).
(defmacro do-hash ((key-var val-var hash-expr &optional result-form) &body body)
(let ((hash-var (gensym "HASH-")))
`(loop with ,hash-var = ,hash-expr
for ,key-var being the hash-keys of ,hash-var
for ,val-var being the hash-values of ,hash-var
do (progn ,@body)
finally (return ,result-form))))
Или функция отображения хеширования:
(defun mapc-hash (hash-table fun)
(loop for key being the hash-keys of hash-table
for value being the hash-values of hash-table
do (funcall fun key value)))
Должен ли язык иметь всевозможные гаджеты, подобные тому, что каждый может написать через минуту?
В общем Lisp имеются батарейки, но они - другие типы батарей: вещи, которые на самом деле трудно сделать. Например, функция compile
для динамической компиляции кода во время выполнения. Для большинства пользователей было бы трудно создать такую вещь с нуля, по сравнению с извлечением ключей или значений из хеш-таблицы в полдюжины различных способов.