Common Lisp: получение всех ключей данной хеш-таблицы в виде списка - PullRequest
20 голосов
/ 15 марта 2012

Интересно, есть ли менее подробный способ, чем использование цикла?В любом случае это работает для меня в 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))

Ответы [ 2 ]

21 голосов
/ 15 марта 2012

Common Lisp появился еще до того, как стала распространяться философия «с батарейками», и ожидается, что большая часть функциональности будет обеспечиваться сторонними библиотеками, а не реализациями.Хотя Common Lisp иногда называют большим языком, его сравнивают только с C и аналогичными, но сам язык довольно мал по сравнению с Python и другими языками с массивными стандартными библиотеками.

Для этой конкретной цели Александрия - это часто используемая коллекция утилит Common Lisp.Среди многих других он содержит hash-table-keys.

10 голосов
/ 16 марта 2012

Нет недостатка в определении

(defun hash-keys (hash-table)
  (loop for key being the hash-keys of hash-table collect key))

, потому что в Common Lisp функция компилируется.Если бы ваш поставщик предоставлял эту функцию, он бы делал то же самое и не был бы намного более эффективным, чем ваш. Если вообще вообще.

В интерпретируемых языках почти все, что вы пишете самостоятельно, имеет недостаток в производительности по сравнению с"внутренняя" рутина.

Извлечение содержимого хэша расточительно;Цикл позволяет вам обрабатывать хэш, не занимая память.Поэтому, возможно, вам нужен макрос вместо этого (некоторые Лиспы предоставляют 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)))

Если язык имееткаждый возможный гаджет, подобный этому, который каждый может написать за минуту?

В Common Lisp есть встроенные батареи, но это другие виды батарей: вещи, которые на самом деле сложно сделать.Например, функция compile для динамической компиляции кода во время выполнения.Большинству пользователей было бы непросто разработать такую ​​вещь с нуля по сравнению с извлечением ключей или значений из хеш-таблицы с полдюжины различными способами.

...