【问题标题】:Knowing when what you're looking at must be a macro知道您正在查看的内容何时必须是宏
【发布时间】:2019-08-16 15:59:35
【问题描述】:

我知道有macro-function,解释了here,它可以让你检查,但是否也可以通过简单地阅读lisp源有时推断出你在看什么“这一定是宏”? (当然假设您以前从未见过函数/宏)。

我相当肯定答案是肯定的,但由于这似乎很重要,我认为值得一问,尤其是因为这方面的任何细微差别都可能很有价值且很有趣。

在 Paul Graham 的 ANSI Common Lisp,p70 中,他描述了如何使用 defstruct

当我看到(defstruct point x y) 时,如果我对defstruct 是什么一无所知,这也可能是一个函数。

但是当我看到

(defstruct polemic
  (subject "foo")
  (effect  "bar"))

我知道 必须 是一个宏,因为(假设)我也知道 subjecteffect 是未定义的函数。 (我知道,因为当他们在“顶层”(?)调用时,undefined function 会出错)(如果这是正确的术语)。

如果上面defstruct 的两个列表参数被引用,就不会那么简单了。因为它们没有被引用,所以它必须是一个宏。

就这么简单吗?

为了让这个问题更清楚,我对书中使用的字段名称稍作更改。

最后,格雷厄姆写道:

“我们可以通过在原始定义的列表中包含字段名称和默认表达式来指定结构字段的默认值”

我注意到这是真的,但它不是(引用的)列表。这篇文章的读者会不会对上面的句子有完全不同的措辞(鉴于书中还没有介绍宏(尽管我对它们有一个基本的了解))。

我的感觉是它不是包含那些默认表达式的“数据列表”。(对不好的术语表示歉意)- 在这里寻求如何正确地概念化。

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    通过模仿现有宏的语法或 CL 的特殊运算符,有一组约定可以非常清楚地确定哪些形式应该是宏。 例如,下面是各种虚构宏的混合,但即使不知道它们的定义,代码也不应该太难弄清楚:

    (defun/typed example ((id (integer 0 10)))
      (with-connection (connection (connect id))
        (do-events (event connection)
          (event-case event
            (:quit (&optional code) (return code))))))
    

    关于宏的通常建议是尽可能避免使用它们,因此,如果您发现某些作为 lisp 表达式没有意义的东西,它可能是或包含在宏中。

    (defstruct point x y)
    

    [...] 如果我对 defstruct 是什么一无所知,这也可以是一个函数。

    有各种提示表明这不是一个函数。首先,名称以def 开头。那么,如果defstruct 是一个函数,那么pointxy 都将在调用函数之前进行评估,这意味着代码将依赖全局变量,即使它们没有戴耳罩(例如*point**x**y*),并且您可能不会在前面的形式中找到它们的任何定义(或稍后在同一编译单元中)。另外,如果它是一个函数,结果将被直接丢弃,因为它没有被使用(这是一个顶级形式)。这仅表明可能存在副作用,但这仍然是不寻常的。 具有副作用的顶级函数看起来像这样,带有引用的数据:

    (register-struct 'point '(x y))
    

    最后,在某些情况下,您无法轻易猜出您使用的是宏还是函数:

    (my-get object :slot)
    

    这可能是一个函数调用,或者您可以有一个宏将上面的内容转换为(aref object 0)(假设:slot 是对象中的第零个槽,因为您的所有对象都被假定为支持某种自定义类型通过向量)。你也可以有编译器宏。如有疑问,请尝试对其进行宏扩展并查看文档。

    【讨论】:

      【解决方案2】:

      一般来说,你是对的:如果调用中有一些嵌套,并且你确定嵌套列表的 car 不是函数 - 它是一个宏。

      另外,def-something 和 with-something 几乎总是宏。

      但不能保证。问题是,你想要完成什么?一些代码遍历/转换或外部处理(如在编辑器中)。对于后者,您应该记住,只有在执行代码评估时才能完全控制,尽管启发式(如在 Emacs 中)可以让您走得很远。或者你只是想培养你的直觉来更快地阅读代码......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-01
        • 1970-01-01
        相关资源
        最近更新 更多