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