roc*_*cia 0 lisp clisp common-lisp
我正在尝试编写一个可以计算GPA的函数.现在我可以做有限的计算(只有3),但我坚持如何计算更多,而不使用循环或递归(这是主题的要求)如何花费第n个函数?像:(nth n),如果是这样,那是否意味着我需要写一个lambda表达式?作为一个新手,我可能没有清楚地描述这个问题,真的需要一些帮助..
Glist是成绩点Clist是学分.
GPA =(gradepoint*credithour + gradepoint*credithour)/(信用的总和)如:(3*1 + 3*2 + 4*1)/(1 + 2 + 1)
这是我的代码:
(defun gpa (Glist Clist)
(format t "~3,2f~%"
(/
(+(nth 0 (mapcar #' * Glist Clist))
(nth 1 (mapcar #' * Glist Clist))
(nth 2 (mapcar #' * Glist Clist)))
(+ (nth 0 Clist)
(nth 1 Clist)
(nth 2 Clist))
);end "/"
);end "format"
(values) );end
Run Code Online (Sandbox Code Playgroud)
编辑
这似乎是一个很好的机会来强调一些常见的(小c)Lisp思想,所以我充实了我的答案来说明.
如另一个答案所述,您可以使用sum对列表(数字)进行操作的函数:
(defun sum (nums)
(reduce #'+ nums))
Run Code Online (Sandbox Code Playgroud)
点积是两个(等长)向量的乘法和:
(defun dot-product (x y)
(sum (mapcar #'* x y)))
Run Code Online (Sandbox Code Playgroud)
该功能gpa是两者的简单组合:
(defun gpa (grades credits)
(/ (dot-product grades credits) (sum credits)))
Run Code Online (Sandbox Code Playgroud)
问题中的示例会得到我们期望的答案(减去被格式化为浮点数):
(gpa '(3 3 4) '(1 2 1))
> 13/4
Run Code Online (Sandbox Code Playgroud)
这个例子中有一些值得一提的东西:
你应该了解map,reduce及其变种和亲属.这些函数对Lisp非常重要,对于在列表上操作非常有用. map*函数通常将序列映射到序列,并且reduce通常将序列转换为单个值(但是您可以使用类似的形式(reduce #'cons '(1 2 3))).
这是"自下而上"编程方法的一个很好的例子; 通过编写sum通常有用的简单函数,您可以轻松地dot-product在其上编写.现在,该gpa函数是一个简单,可读的功能,建立在另外两个之上.这些都是单行的,所有具有CL基础知识的人都可以轻松阅读.这与通常应用于OOP的方法形成对比.
没有重复的代码.当然,sum不止一次使用,但只在有意义的地方使用.你可以做更多的事情来抽象列表元素之和的概念.在Scheme中用函数编写函数更自然,这是一个完全不同的主题.这是一个简单的例子,但没有两个函数做同样的事情.