【问题标题】:Creation of similar functions using Lisp macro使用 Lisp 宏创建类似的函数
【发布时间】:2014-09-19 20:55:03
【问题描述】:

在我的工作中,我尝试在 Common Lisp 中使用宏并有一些问题。 我有两个功能

(defun when-tagflag ()
  (when (= tagflag 1)
   (setf tagflag 0)
   (push tagbuf taglist)
   (setf tagbuf "")))


 (defun when-attrflag ()
  (when (= attrflag 1)
   (setf attrflag 0)
   (push attrbuf attrlist)
   (setf attrbuf "")))

非常相似的功能。经过几个小时的实验,我得到了这样一个宏

defmacro when-flag (name)
 (let ((flag (read-from-string (concatenate 'string (string name) "flag")))
       (lst (read-from-string (concatenate 'string (string name) "list")))
       (buf (read-from-string (concatenate 'string (string name) "buf"))))
 `(when (= ,flag 1)
   (setf ,flag 0)
   (push ,buf ,lst)
   (setf ,buf ""))))


 > (pprint (macroexpand-1 '(when-flag "tag")))
 > (WHEN (= TAGFLAG 1) (SETF TAGFLAG 0) (PUSH TAGBUF TAGLIST) (SETF TAGBUF ""))

在 when-flag 中,我使用 concatenate string 和 read-from-string ,但我认为我的方法不是规范的。有没有更合适的方法来解决这样的问题?

附:这个解决方案对我不起作用Can you create interactive functions in an Emacs Lisp macro?

【问题讨论】:

  • (setf attrlist (push attrbuf attrlist)) 只是(push attrbuf attrlist)
  • @RainerJoswig thx 提示 :) 我是 lisp 的新手)
  • 我已经更改了标签:该语言称为 Common Lisp,而不是 Clisp。
  • 仅供参考,这给我敲响了一些警钟。您使用的多个数字标志非常相似,以至于您需要这样的宏,并且您似乎正在改变至少四个全局变量。如果我有这样的代码,我会非常仔细地查看它,看看是否有更好的方式来表达我的意图。完成后考虑在CR 提交。
  • @Inaimathi 谢谢你的评论。我同意这是错误的。所有当函数都是闭包的一部分。但我没有在我的问题中添加这个。这是一些任务的原型,当我考虑重构时,我看到了这些函数之间的相似之处。我想:“宏可以帮助我完成这项任务吗?”

标签: macros lisp common-lisp metaprogramming


【解决方案1】:

Common Lisp 中的符号名称在内部默认为大写。

CL-USER 10 > (intern (concatenate 'string "TAG" "FLAG") "CL-USER")
TAGFLAG
:INTERNAL

CL-USER 11 > (intern (format nil "~:@(~AFLAG~)" "TAG") "CL-USER")
TAGFLAG
:INTERNAL

例子:

(defmacro when-flag (prefix &key (package-name "CL-USER"))
  (flet ((create-symbol (suffix)
           (intern (format nil "~:@(~A~A~)" prefix suffix)
                   package-name)))
    (let ((flag-sym (create-symbol "FLAG"))
          (list-sym (create-symbol "LIST"))
          (buf-sym  (create-symbol "BUF")))
      `(when (= ,flag-sym 1)
         (setf ,flag-sym 0)
         (push ,buf-sym ,list-sym)
         (setf ,buf-sym "")))))

【讨论】:

  • 谢谢)我尝试了符号和实习生函数,现在我发现出了什么问题。我用小写字符串实习生。那么从字符串读取的方法呢?这是正确的解决方案?
猜你喜欢
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 2023-03-08
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
相关资源
最近更新 更多