2013-04-11 75 views
2

我需要的時候,我發現我一直在尋找從maphash提前退出。如何擺脫Emacs Lisp中的maphash?

(defun find-in-hash (str hash) 
    (let ((match nil)) 
    (maphash (lambda (key value) 
     (if (string-prefix-p str key) 
     (setq match key))) hash) 
    match)) 

我會如何的Emacs Lisp做到這一點?

+1

是[的Emacs Lisp:方式可以退出/打破循環](HTTP:// ergoemacs.org/emacs/elisp_break_loop.html)或幫助[如何中斷maphash(http://osdir.com/ml/lisp.allegro/2006-04/msg00018.html)? – 2013-04-11 07:04:52

+0

這不是一個正確的形式(不匹配的括號,誤導的縮進)。 – Svante 2013-04-11 07:06:47

+1

你有沒有想過使用一個trie而不是? – Svante 2013-04-11 07:07:05

回答

5

如所解釋的在how to interrupt maphash可以放置一個maphash塊內部,並經由return-from退出塊,即使用形式

(block stop-mapping 
    (maphash 
    ;; Function to call for all entries in ht. 
    ;; A condition for when to stop mapping. 
    (return-from stop-mapping) 
    ht)) 

注意,這需要cl其可以經由(require 'cl)是必需的。 As mentioned in a comment相同的結果可以以純淨的elisp通過

(catch 'stop-mapping 
    (maphash 
    ;; Function to call for all entries in ht. 
    ;; A condition for when to stop mapping. 
    (throw 'stop-mapping retval) 
    ht)) 
+0

上面的代碼需要使用'cl'。如果用'catch'stop-mapping'和'throw'stop-mapping'將'block stop-mapping'替換爲'from-top-mapping',則可以在「plain Elisp」中得到相同的結果。 – Stefan 2013-04-11 12:23:59

+0

@Stefan但是在我的Emacs安裝過程中,'block'和'return-from'似乎都可用,因爲它們都有記錄。 – 2013-04-11 12:27:28

+3

它們只有在你(需要'cl')後纔可用。很可能你正在使用的其他軟件包已經完成了「require」,這就是你看到它們的原因。在任何情況下,'block'和'return-from'都是在'cl'包中實現的宏,它們擴展爲使用'catch'和'throw'的代碼。 – Stefan 2013-04-11 12:29:36

3

實現自我宣傳在這裏:)

我已經工作(雖然不是相當多最近)在一組宏到位使它更統一,並且希望更容易對Emacs Lisp中可用的各種集合進行各種迭代。那就是:https://code.google.com/p/i-iterate/它不是100%完成,測試,但在大多數情況下它是。

正如前面已經說過,從maphash打破的唯一方法是拋出一個錯誤。但這只是Emacs Lisp在設計時獲得的。許多老的語言有特殊的原語遍歷特別是集合,或用於執行數值迭代,而他們沒有迭代的語言級別的抽象。 loop Emacs Lisp中的cl包中的宏是解決這種情況的一種(好)方法,但就其本質而言,它必須鏡像Common Lisp中的同一個宏,並且該宏不可擴展(您不能將自己的驅動程序添加到它,即使某些實現允許它)。

我曾在試圖在精神上跟隨另一Common Lisp的庫庫:iterate,並從那裏借用了很多想法。

只是爲了說明什麼loop宏可以這樣做:

(loop with hash = (make-hash-table) 
     initially 
     (setf (gethash 'a hash) 'b 
      (gethash 'b hash) 'b 
      (gethash 'c hash) 'c)  ; initialize variables 
             ; before any iteration happens 
     for x being the hash-key in hash 
     using (hash-value y)    ; define variables used in iteration 
     collect (list x y) into z  ; some predefined functionality 
     until (eq x y)     ; termination condition 
     finally (return (cons 'd z))) ; returning from iteration 
;; (d (a b) (b b)) 

隨着它哈希表,數組或列表和類似的工作效益。

使用類似的代碼++宏:

(++ (with ((hash (let ((h (make-hash-table))) 
        (setf (gethash 'a h) 'b 
         (gethash 'b h) 'b 
         (gethash 'c h) 'c) h)))) 
    (for (x . y) pairs hash) 
    (collect (list x y) into z) 
    (when (eq x y) (return (cons 'd z)))) 
;; (d (b b) (a b)) 

(我沒有什麼類似initially還)