2012-03-15 66 views
19

我在想,是否有比使用循環更少的詳細方式。反正這對我的作品在CLISP:Common Lisp:將給定哈希表的所有密鑰作爲列表獲取

(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)) 

回答

20

Common Lisp的來自「電池包料」的理念開始流行之前,大部分功能有望通過第三方庫,而不是實現來提供。雖然Common Lisp有時被稱爲大型語言,但它僅與C和類似語言相比較,與Python和其他帶有大量標準庫的語言相比,該語言本身相當小。

爲此特定目的,Alexandria是Common Lisp實用程序的常用集合。其中包含許多其他東西hash-table-keys

+2

Common Lisp當時非常「包含電池」。人們只是期待更多(和不同種類)的電池。 – Xach 2012-03-15 19:21:05

+1

與C相比,Common Lisp現在只有稍大一點,它現在正推動接近700頁的ISO標準。 (並且僅僅是比1989年更多的「電池包含」語言,當時它是200頁的頁面。) – Kaz 2012-03-15 22:24:46

+0

現在很流行的大多數「包含電池」的語言**都是**,因爲函數你寫自己有一個性能劣勢。 – Kaz 2012-03-15 22:25:33

9

有,因爲Common Lisp中的函數編譯定義

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

沒有缺點。如果你的供應商提供了這個功能,它幾乎可以做同樣的事情,並且不會比你的效率更高。

在解釋型語言中,與「內部」例程相比,幾乎任何自己編寫的東西都具有性能劣勢。

包含散列的內容是浪費的;循環可以讓你處理散列,而不用考慮內存。所以也許你想要一個宏而不是(一些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))) 

如果該語言有每一個可能的小工具,這樣任何人都可以在一分鐘內寫?

在常見的Lisp中,包含電池,但它們是其他類型的電池:實際上很難做到的事情。例如,一個compile函數用於在運行時動態編譯代碼。對於大多數用戶來說,從頭開始開發這樣的東西相比從哈希表中以六種不同的方式拉取鍵或值是極其困難的。

+0

(更不用提你在這裏展示的宏定義設施了:))。 – 2014-05-27 11:36:47