我可以在emacs lisp宏中放入条件吗? [英] Can I put condition in emacs lisp macro?

查看:97
本文介绍了我可以在emacs lisp宏中放入条件吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何实现这样的目标?

(defmacro mood (x)
  (if (equal (symbol-name x) "t")
      `(defun happy ()
         (message "Happy"))
    `(defun sad ()
       (message "Sad")))
  )

我的目标是基于参数创建不同的函数. 这样做有什么问题吗?

My aim is to create different function base on argument. Is there any problem doing so?

推荐答案

您是正确的-对于在扩展时评估的代码完全的情况依赖于(未求值的)宏参数的值,我相信基于这些参数有条件地生成宏的返回格式是安全的.

Edit 2: You're right -- for cases in which the code being evaluated at expansion-time is entirely dependent on the values of the (unevaluated) macro arguments, I believe it is safe for the macro's returned form to be generated conditionally, based upon those arguments.

您只需要意识到,任何以 dynamic 值为条件的行为都必须作为扩展形式的一部分来处理.

You just need to be aware that any behaviour which is conditional upon dynamic values needs to be dealt with as a part of the expanded form.

(例如,如果宏参数是一个变量,而您正在条件中测试变量的,则该测试在扩展时进行是不安全的,因为该值是可能会在宏的扩展时间和评估扩展代码的时间之间变化.)

(e.g. if the macro argument were a variable, and you were testing the value of the variable in your condition, it would be unsafe for that test to occur at expansion time, as that value is liable to vary between the macro's expansion time, and the time(s) that the expanded code is evaluated.)

因此,您所提问题的具体示例确实是安全的,因此在这种情况下,我的变体(以下)实际上是不必要的.但是,一般来说,扩展时间评估肯定是您要谨慎的事情.

So the specific example in your question is indeed safe as-is, and therefore my variations (below) are not actually necessary in this case. However expansion-time evaluations are certainly something you will want to be cautious about in general.

随后是最初的答案...

宏在编译时扩展. (或者在Emacs的最新版本中,如果没有可用的字节编译库,通常会在加载时间对其进行急切"编译.)

Macros are expanded at compile time. (Or in recent versions of Emacs, should no byte-compiled version of the library be available, they will usually be compiled "eagerly" at load time).

在这些情况下,任何不属于宏返回形式的代码都将在每个会话中最多评估一次,但很可能仅对一次进行一次评估.对于给定的代码扩展(然后可能会多次调用扩展的代码).

In these scenarios, any code which is not a part of the form returned by the macro will be evaluated at most once per session, but quite likely just once ever for a given expansion of the code (whereas the expanded code might then be called numerous times).

如果您需要扩展的代码在运行时有条件地执行操作,则条件必须是宏返回的表单的一部分.

If you need your expanded code to act conditionally at run-time, the conditions must be a part of the form returned by the macro.

例如,我想您实际上想写一些类似的东西:

For example, I imagine you actually wanted to write something more like:

(defmacro mood (x)
  `(if (equal (symbol-name ,x) "t")
       (defun happy ()
         (message "Happy"))
     (defun sad ()
       (message "Sad"))))

尽管您(几乎)永远不想通过比较符号symbol-name来比较符号.您已经假设宏参数将评估为符号,因此只需将符号与eq进行直接比较:

Although you would (almost) never want to compare symbols by comparing their symbol-name. You've already made the assumption that the macro argument will evaluate to a symbol, so just compare the symbols directly with eq:

(defmacro mood (x)
  `(if (eq ,x t)
       (defun happy ()
         (message "Happy"))
     (defun sad ()
       (message "Sad"))))

然后,例如,(mood 'foo)扩展为(由 M-x pp-macroexpand-last-sexp提供):

Then for example, (mood 'foo) expands to (courtesy of M-x pp-macroexpand-last-sexp):

(if
    (eq 'foo t)
    (defun happy nil
      (message "Happy"))
  (defun sad nil
    (message "Sad")))

这篇关于我可以在emacs lisp宏中放入条件吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆