【问题标题】:How to break out from maphash in Emacs Lisp?如何从 Emacs Lisp 中的 maphash 中脱颖而出?
【发布时间】:2017-11-01 20:31:17
【问题描述】:

当我找到我要找的东西时,我需要提前从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 中执行此操作?

【问题讨论】:

  • 这不是一个正确的形式(不匹配的括号,误导性缩进)。
  • 您是否考虑过使用 trie 代替?
  • @N.N 当然! blockreturn-from 似乎正是我想要的!
  • @Svante 好点!尽管 trie 不适合这种特定情况。代码脱离上下文并稍作修改。

标签: emacs elisp


【解决方案1】:

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

【讨论】:

  • 以上代码需要使用cl。如果将 block stop-mapping 替换为 catch 'stop-mapping 并将 return-from top-mapping 替换为 throw 'stop-mapping,则可以在“plain Elisp”中获得相同的结果。
  • 只有在您 (require 'cl) 之后才能使用它们。您正在使用的其他一些软件包很可能已经完成了这个require,这就是您看到它们的原因。在任何情况下,blockreturn-from 都是在 cl 包中实现的宏,它们扩展为使用 catchthrow 的代码。
  • @Stefan 我明白了。谢谢提供信息。我已经相应地更新了答案。
【解决方案2】:

这里有点自我推销:)

我一直在研究一组宏(尽管最近没有那么多),以使其更加统一,并且希望更容易对 Emacs Lisp 中可用的各种集合进行各种迭代。它是:https://code.google.com/p/i-iterate/ 它不是 100% 完成和测试的,但大部分是。

正如已经说过的,打破maphash 的唯一方法是抛出一个错误。但这只是 Emacs Lisp 在设计时获得的东西。许多较旧的语言具有用于迭代特定集合或执行数字迭代的特殊原语,而它们没有语言级别的迭代抽象。 Emacs Lisp 中 cl 包中的 loop 宏是解决这种情况的一种(好)方法,但从本质上讲,它必须镜像 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 的东西)

【讨论】:

    猜你喜欢
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2012-03-17
    • 2017-03-19
    相关资源
    最近更新 更多