矩阵相加 Lisp
(defun (matrix-add m1 m2)
(defun (matrix-add-row r1 r2 res-row)
(if (and (not (null? r1)) (not (null? r2)))
(matrix-add-row (cdr r1) (cdr r2)
(cons (+ (car r1) (car r2)) res-row))
(reverse res-row)))
(defun (matrix-add-each m1 m2 res)
(if (and (not (null? m1)) (not (null? m2)))
(let ((res-row (matrix-add-row (car m1) (car m2) ())))
(matrix-add-each (cdr m1) (cdr m2) (cons res-row res)))
(reverse res)))
(matrix-add-each m1 m2 ()))
嗨,我在一张纸上进行了矩阵加法,但现在当我输入 lisp 时它就可以工作了。 怎么了?
(defun (matrix-add m1 m2)
(defun (matrix-add-row r1 r2 res-row)
(if (and (not (null? r1)) (not (null? r2)))
(matrix-add-row (cdr r1) (cdr r2)
(cons (+ (car r1) (car r2)) res-row))
(reverse res-row)))
(defun (matrix-add-each m1 m2 res)
(if (and (not (null? m1)) (not (null? m2)))
(let ((res-row (matrix-add-row (car m1) (car m2) ())))
(matrix-add-each (cdr m1) (cdr m2) (cons res-row res)))
(reverse res)))
(matrix-add-each m1 m2 ()))
Hi I matrix addition on a piece of paper but it's now working when I type in lisp..
What's wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,语法既不是 common lisp 也不是 schema,这两种常用的主要 lisp 方言。
在 common-lisp 语法中,这按预期工作:
有一些事情比这里所要求的要详细一些。
首先,在common lisp中,nil为假,
and
返回最后一个不为假的参数。因此,在您的情况下,在 common lisp 中,您不需要所有非空测试。
其次,使用尾递归函数而不是基于累加器的函数是很常见的(在方案中比在 lisp 中更常见),因此,在不使用库函数的情况下添加两个列表通常会采用两个列表,并返回一个其头为头的列表。两个列表的头部之和,其尾部是将每个列表尾部的元素相加的结果。因此,您可以将函数编写为采用两个参数并根据这两个参数返回结果的一部分,而不是采用三个参数(输入、输入、累加器),然后反转累加器。
但是这种将函数应用于列表的汽车并将该函数应用于列表的其余部分的模式非常常见,因此有一组库函数 - 地图系列。
因此,您倾向于使用映射函数来操作简单列表,而不是编写自己的列表。
# '
读取器宏(function
的缩写)从符号中提取函数,因此要将+
函数应用于两个列表的元素可以使用mapcar:这消除了为递归应用程序编写样板的复杂性,它可能更有效,并且表达了更高级别的意图。
由于您不再需要累加器,因此不需要定义matrix-add-each,而只需返回将add-row函数应用于矩阵中的每一行的结果:
或者您甚至可以使用lambda比单独定义函数,尽管从阅读拆分版本开始可能更容易一些:
尽管对于“真实”函数,您可能需要检查矩阵的大小是否相同以及行的大小是否相同,这比单行函数更复杂。但对于真正的矩阵代码,您可能希望使用数组而不是列表。
一旦你开始考虑列表上的函数,以及在列表上应用函数的函数,你会开始发现你需要做更少的工作来让 lisp 做你想做的事情。
正如评论所指出的,defun 在本地范围内创建全局函数绑定、flet 和标签。
First off, the syntax is neither common lisp nor scheme, the two main lisp dialects which are in common use.
In common-lisp syntax this works as expected:
The are a few things which are a bit more verbose than required here.
Firstly, in common lisp, nil is false, and
and
returns the last argument which is not false.so in your case, in common lisp, you don't need all the not null tests.
Secondly, it's common (more so in scheme than in lisp) to use tail recursive functions rather than accumulator based ones, so rather to add two lists without using the library functions you would typically take two lists, and return a list whose head is the sum of the heads of the two lists, and whose tail is the result of adding the elements of each lists tails. So instead of taking three arguments (input, input, accumulator), then reversing the accumulator, you would write the function as taking two arguments and returning the part of the result based on those two arguments.
But this pattern of applying a function to the car of lists and applying the function to the rest of the list is very common, so there are a set of library functions for it - the map family.
So you would tend to use map functions to operate on simple lists rather than writing your own. The
#'
reader macro (short forfunction
) extracts a function from a symbol, so to apply the+
function to the elements of two lists you can usemapcar
:This removes the complexity of having to write the boiler-plate for the recursive application, it may be a more efficient, and expresses the higher level intent.
Since you no longer need the accumulator, you don't need to define matrix-add-each, and instead can simply return the result of applying the add-row function to each row in the matrix:
or you can even use a lambda rather than defining the function separately, though it might be a bit easier to read the split-up version to start with:
Though for a 'real' function you might want to check that the matrices are the same size and the rows are the same size, which would be more complicated than a single line function. But for real matrix code you might want to be using arrays rather than lists anyway.
Once you start thinking in terms of functions over lists, and functions applying functions over lists, you'll start to find you have to do much less work to get lisp to do what you want it to.
As comments pointed out,
defun
creates a global function binding,flet
andlabels
at local scope.