Macros LISP中的求和宏和乘积宏

Macros LISP中的求和宏和乘积宏,macros,sum,lisp,tail-recursion,Macros,Sum,Lisp,Tail Recursion,我需要写一个程序,它在某个变量范围内计算某个物体的总和,比如: 和范围i 2 N sin i 一般来说: 求和范围迭代变量begin end my body 为此: 产品也是如此。我不能使用任何循环/迭代构造,只为自己编写一个,使用尾部递归 我需要用宏来完成,但我对这些东西没有概念。我不需要完整的代码,只需要一些宏和用法的解释。首先,变量迭代如何将变量传递给sin?如何在宏中实现尾部递归 据我所知,宏创建了一些列表,这些列表被替换到调用和计算的位置。我说得对吗?所以我的解决方案是为2到N之间的每

我需要写一个程序,它在某个变量范围内计算某个物体的总和,比如:

和范围i 2 N sin i

一般来说:

求和范围迭代变量begin end my body

为此:

产品也是如此。我不能使用任何循环/迭代构造,只为自己编写一个,使用尾部递归

我需要用宏来完成,但我对这些东西没有概念。我不需要完整的代码,只需要一些宏和用法的解释。首先,变量迭代如何将变量传递给sin?如何在宏中实现尾部递归


据我所知,宏创建了一些列表,这些列表被替换到调用和计算的位置。我说得对吗?所以我的解决方案是为2到N之间的每个i创建sini的列表,然后将+`应用于这个列表。可以吗?

首先,你应该看看你想写什么,然后看看它应该扩展到什么代码

宏将代码的输入形式作为参数进行转换。因此,参数列表需要具有您想要编写的内容的结构

在你的情况下,你想写作

(sum-range (iteration-variable begin end) #|my-body|#)
我的身体是一些用变量计算的形式。您可以将其指定为单个表单,但有时在这样的主体中进行任意计算很方便,因此我将允许下面的一般情况

然后,您的参数列表需要反映我使用var而不是迭代变量:

现在,如果没有宏,您需要编写什么?您使用var在范围内循环求和body的求值。幸运的是,对于这种解释,这可以很好地转换为循环构造

(loop :for var :from begin :to end
      :sum #|what to sum with var...|#)
所以宏需要生成这样一个表单。我们有非常好的代码模板语法Quasikote,可以很好地表达这一点:

(defmacro sum-range ((var begin end) &body body)
  `(loop :for ,var :from ,begin :to ,end
         :sum (progn ,@body)))
progn允许正文中有多个表单,返回最后一个表单的值

这和写作差不多

(defmacro sum-range ((var begin end) &body body)
  (list 'loop :for var :from begin :to end
        :sum (list* 'progn body)))
现在,当你写作的时候

(sum-range (i 2 n)
  (sin i))
它将扩展到宏

(loop :for i :from 2 :to n
      :sum (progn
             (sin i)))

现在,您的任务是用尾部递归函数替换循环解决方案。您应该首先定义递归函数,然后使用宏将代码转换为该函数的调用。将主体传递给该函数可以通过将其包装在lambda匿名函数中来完成。

首先,您应该查看要编写的内容,然后查看它应该扩展到什么代码

宏将代码的输入形式作为参数进行转换。因此,参数列表需要具有您想要编写的内容的结构

在你的情况下,你想写作

(sum-range (iteration-variable begin end) #|my-body|#)
我的身体是一些用变量计算的形式。您可以将其指定为单个表单,但有时在这样的主体中进行任意计算很方便,因此我将允许下面的一般情况

然后,您的参数列表需要反映我使用var而不是迭代变量:

现在,如果没有宏,您需要编写什么?您使用var在范围内循环求和body的求值。幸运的是,对于这种解释,这可以很好地转换为循环构造

(loop :for var :from begin :to end
      :sum #|what to sum with var...|#)
所以宏需要生成这样一个表单。我们有非常好的代码模板语法Quasikote,可以很好地表达这一点:

(defmacro sum-range ((var begin end) &body body)
  `(loop :for ,var :from ,begin :to ,end
         :sum (progn ,@body)))
progn允许正文中有多个表单,返回最后一个表单的值

这和写作差不多

(defmacro sum-range ((var begin end) &body body)
  (list 'loop :for var :from begin :to end
        :sum (list* 'progn body)))
现在,当你写作的时候

(sum-range (i 2 n)
  (sin i))
它将扩展到宏

(loop :for i :from 2 :to n
      :sum (progn
             (sin i)))

现在,您的任务是用尾部递归函数替换循环解决方案。您应该首先定义递归函数,然后使用宏将代码转换为该函数的调用。将主体传递给该函数可以通过将其包装在lambda匿名函数中来完成。

那么对于i 1 1000,您将在列表中创建1000个sin调用?这有意义吗?那么对于i 1000,你会在一个列表中创建1000个sin调用?这有意义吗?我可以用标签或let在内部定义loop func吗?当然可以,但这意味着宏将在您使用它的每个地方扩展到该创建。我发现把它放在外面更清楚。我可以用标签或let在里面定义loop func吗?是的,当然,但这意味着宏将在您使用它的每个地方扩展到该创建。我发现把它放在外面更清楚。