macros - 是否有用于构建列表的现有 lisp 宏?

标签 macros lisp elisp

在 Python 中,我可以使用 yield 来构建列表,而无需定义临时变量:

def get_chars_skipping_bar(word):
    while word:

        # Imperative logic which can't be
        # replaced with a for loop.
        if word[:3] == 'bar':
           word = word[3:]
        else:
            yield foo[0]
            foo = foo[1:]

在 elisp 中,我看不到有任何方法可以做到这一点,无论是内置的还是使用任何预先存在的库。我不得不手动建立一个列表并对其调用 nreverse。由于这是一种常见模式,我编写了自己的宏:

(require 'dash)
(require 'cl)

(defun replace-calls (form x func)
  "Replace all calls to X (a symbol) in FORM,
calling FUNC to generate the replacement."
  (--map
   (cond
    ((consp it)
     (if (eq (car it) x)
         (funcall func it)
       (replace-calls it x func)))
    (:else it))
   form))

(defmacro with-results (&rest body)
  "Execute BODY, which may contain forms (yield foo).
Return a list built up from all the values passed to yield."
  (let ((results (gensym "results")))
    `(let ((,results (list)))
       ,@(replace-calls body 'yield
                        (lambda (form) `(push ,(second form) ,results)))
       (nreverse ,results))))

示例用法:

(setq foo "barbazbarbarbiz")

(with-results
 (while (not (s-equals? "" foo))
   ;; Imperative logic which can't be replaced with cl-loop's across.
   (if (s-starts-with? "bar" foo)
       (setq foo (substring foo 3))
     (progn
       (yield (substring foo 0 1))
       (setq foo (substring foo 1))))))

在 elisp、cl.el 或库中一定有更好的方法或现有解决方案。

最佳答案

Python 函数实际上是一个生成器。在 ANSI Common Lisp 中,我们通常会使用词法闭包来模拟生成器,或者使用库来直接定义生成器,例如 Pygen。 .也许这些方法可以移植到 Emacs Lisp。

关于macros - 是否有用于构建列表的现有 lisp 宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23918121/

相关文章:

c++ - 有没有跨平台的方法来检测 Debug模式编译?

scope - 在本地环境中定义和访问变量

c++ - 为什么 token 连接在 C++ 中不起作用?

lisp - 我可以将函数 "get"与关联列表一起使用吗?

Emacs lisp - 如何尝试/捕获处理错误?

使用类函数宏编译错误

macros - 为什么符号 pat ... 表示方案宏模式中的零个或多个表达式

recursion - CLISP dfs 获取程序堆栈溢出

Emacs/Emacs Lisp : can I insert advice before interactive form? 或者如何智能预设编译命令?

emacs - 如何使用 Emacs 的 DBUS 接口(interface)?