Function 是否存在不能表示为函数的宏?

Function 是否存在不能表示为函数的宏?,function,macros,lisp,Function,Macros,Lisp,是否有任何宏: 不能表示为等效的函数,或者: 很难将表示为等效的函数,或者: 在性能方面明显低于同等的功能 你能给出这样一个宏(和函数)的例子吗 我的问题特别涉及到的宏和函数,但您可以更一般地处理这个问题。我对递归宏特别感兴趣 编辑: 我应该说得更具体些。当我问上述问题时,我记住了我的Lisp项目的特定上下文,这是一种数学计算器 我想知道是否有充分的理由将宏用于任何数学运算,例如: 分析 分析 行动 计算给定函数 计算 等等 出于某种原因,我需要为这个项目使用一些递归宏。因此,如果我能

是否有任何

  • 不能表示为等效的函数,或者:
  • 很难将表示为等效的函数,或者:
  • 性能方面明显低于同等的功能
你能给出这样一个宏(和函数)的例子吗

我的问题特别涉及到的宏和函数,但您可以更一般地处理这个问题。我对递归宏特别感兴趣


编辑:

我应该说得更具体些。当我问上述问题时,我记住了我的Lisp项目的特定上下文,这是一种数学计算器

我想知道是否有充分的理由将宏用于任何数学运算,例如:

  • 分析
  • 分析
  • 行动
  • 计算给定函数
  • 计算
  • 等等
出于某种原因,我需要为这个项目使用一些递归宏。因此,如果我能重新表述我的问题:


你能举例说明在符号计算中巧妙地使用[recursive]宏吗


任何不求值的Lisp宏(“两次”,因为它是一个宏)其参数都不能表示为函数,因为函数应用是在求值的参数上完成的。例如,您可以定义一个宏
my if
,其行为与
if
完全相同(并且
if
不能是函数)

C.Queinnec的书非常详细地解释了这一点(并且有几章是关于宏的)。我强烈建议你读一读(因为回答你过于宽泛的问题可能需要一整本书,而不是一段)

如果宏将某个参数展开几次,它可能会比等效函数慢(因为如果展开两次,某些子计算可能会进行两次)

(当然,你所有问题的答案都可以是肯定的;我留给你如何找到一些例子)


顺便说一句,这在C中甚至是正确的…

任何不求值的Lisp宏(“两次”,因为它是一个宏)其参数不能表示为函数,因为函数应用是在求值的参数上完成的。例如,您可以定义一个宏
my if
,其行为与
if
完全相同(并且
if
不能是函数)

C.Queinnec的书非常详细地解释了这一点(并且有几章是关于宏的)。我强烈建议你读一读(因为回答你过于宽泛的问题可能需要一整本书,而不是一段)

如果宏将某个参数展开几次,它可能会比等效函数慢(因为如果展开两次,某些子计算可能会进行两次)

(当然,你所有问题的答案都可以是肯定的;我留给你如何找到一些例子)

顺便说一句,这在C

是否有任何

  • 不能表示为等效的函数,或者:
  • 很难将表示为等效的函数,或者:
  • 性能方面明显低于同等的功能
答案从来没有这么简单。通常是“是”和“否”。在我看来,宏有两大优势:语法计算。例如,宏(如带有打开文件的)允许您编写:

(with-open-file (var "some-filename")
  ; operations with var
  )
几乎只是语法上的糖

(let ((x (open ...)))
  (unwind-protect 
    (funcall (lambda (var) 
               ; operations with var
               )
              x)
    ; cleanup forms
    ))
这是一种延迟求值和语法糖的混合,取决于你如何看待它。它是延迟求值,因为所有使用var的操作都被包装到一个lambda函数中。这也是语法上的甜点,因为你可以很明显地将上面的内容抽象为:

(defun call-with-open-file (open-args function)
  (let ((x (apply 'open open-args)))
    (unwind-protect (funcall function x)
      ; cleanup forms
      )))
然后,打开文件就是语法糖:

(defmacro with-open-file ((var &rest open-args) &body body)
  `(call-with-open-file (list ,@open-args)
     (lambda (,var) ,@body)))
这是一个典型的例子,展示了延迟评估(身体形式)和围绕功能接口的语法糖。您通常可以这样做。例如,使用if,您可以编写一个功能界面:

(defun %if (condition then &optional (else (constantly nil)))
  `(funcall (cond (condition then) (t else))))
然后如果可以将实现为宏:

(defmacro if (condition then &optional else)
  `(%if condition (lambda () ,then) (lambda () ,else)))
如果和其他条件形式有点独特,但是从这个意义上说,因为实现最终必须为您提供一些条件操作。不过,该运算符通常不是宏,而是一种特殊形式

其他特殊宏(如loop)如何定义特定于域的语言?您也可以这样做,但最终会让函数接受宏版本的“主体”,并在运行时对其进行解释。例如,你可以这样做

(defun %loop (&rest loop-body)
  ; interpret body
  )
但这显然将是一个巨大的性能打击

所以,我假设没有没有没有语义等价物的宏,但是这些宏需要一些不同的参数。其中一些语义等价的函数很难表达,而其中一些函数(例如,在传递匿名函数时)的性能肯定会差得多

是否有任何

  • 不能表示为等效的函数,或者:
  • 很难将表示为等效的函数,或者:
  • 性能方面明显低于同等的功能
答案从来没有这么简单。通常是“是”和“否”。在我看来,宏有两大优势:语法计算。例如,像这样的宏