在宏中获取类型信息 [英] Get the type information in macros

查看:125
本文介绍了在宏中获取类型信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(defmacro test (&key list &environment env)
  (typecase (get-type list env)
    (list `(do-something (list ,@list)))
    (integer `(do-something (list ,list ,list ,list)))))

(test :list '(1 2 3)) ; => (do-something (list 1 2 3))
(test :list (* 1 2)) ; => (do-something (list (* 1 2) (* 1 2) (* 1 2)))

是否可以在宏扩展时获取list的类型? (我叫get-type)

Is it possible to get the type of list at macroexpansion-time? (what I called get-type)

它不适用于评估,因为此时变量可能不存在,并且可能会更改某些其他值,因此不应更改.

It won't work with evaluation, because the variables may not be existent at this time, and maybe some other values will be changed, that should not be changed.

还是应该让我的宏扩展形式也称为Typecase?

Or should I let my macro-expansion be a form, that also calls typecase?

推荐答案

除了 Rainer的出色答案,请注意,Common Lisp包含 constantp 采用某种形式和环境.这不会涵盖所有情况,因为有人可以用变量而不是常量形式调用您的宏,但是如果您 do 获得常量形式,则可以在编译时检查其类型:

In addition to Rainer's excellent answer, do be aware that Common Lisp includes the function constantp which takes a form and an environment. This wont' cover every case, since someone could call your macro with a variable rather than a constant form, but in the case that you do get a constant form, you can check its type at compile time:

(defmacro foo (arg &environment environment)
  (if (constantp arg environment)
      (typecase arg
        (string 'string-expansion)
        (vector 'vector-expansion)
        (number 'number-expansion)
        (t 'constant-but-other-type-expansion))
      'nonconstant-expansion))

CL-USER> (macroexpand '(foo "hello"))
STRING-EXPANSION
T
CL-USER> (macroexpand '(foo #(1 2 3)))
VECTOR-EXPANSION
T
CL-USER> (macroexpand '(foo 42))
NUMBER-EXPANSION
T
CL-USER> (macroexpand '(foo 'something-else))
CONSTANT-BUT-OTHER-TYPE-EXPANSION
T
CL-USER> (macroexpand '(foo bar))
NONCONSTANT-EXPANSION
T

现在,这似乎有点round回,但在某些地方它可能会有用.

Now, this may seem a bit roundabout, but it can be useful in some places.

或者我应该让我的宏扩展程序作为一种形式,这也称为 键入大小写?

Or should I let my macro-expansion be a form, that also calls typecase?

如果您查看序列操纵函数的开源实现,您可能会发现一些非常有趣的代码示例.许多常见的Lisp函数(例如 reduce )采用序列,这些序列可以是列表,也可以是向量.不幸的是,在这两种类型上有效实现 reduce code 是不同的.例如,看看 SBCL的序列函数.您将开始了解他们如何处理此问题.您可能还想看看编译器宏.

You may find some very interesting code examples if you look in open source implementations of sequence manipulation functions. Many Common Lisp functions (e.g., reduce) take sequences, and these can be either lists or vectors. Unfortunately, the code to implement reduce efficiently on these two types is different. E.g., have a look at SBCL's sequence functions. You'll start to get a feel for how they handle this issue. You may also want to have a look at compiler macros.

这篇关于在宏中获取类型信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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