常见的lisp中Nth的问题

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)

Kei*_*yne 7

编辑

这似乎是一个很好的机会来强调一些常见的(小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)

这个例子中有一些值得一提的东西:

  1. 你应该了解map,reduce及其变种和亲属.这些函数对Lisp非常重要,对于在列表上操作非常有用. map*函数通常将序列映射到序列,并且reduce通常将序列转换为单个值(但是您可以使用类似的形式(reduce #'cons '(1 2 3))).

  2. 这是"自下而上"编程方法的一个很好的例子; 通过编写sum通常有用的简单函数,您可以轻松地dot-product在其上编写.现在,该gpa函数是一个简单,可读的功能,建立在另外两个之上.这些都是单行的,所有具有CL基础知识的人都可以轻松阅读.这与通常应用于OOP的方法形成对比.

  3. 没有重复的代码.当然,sum不止一次使用,但只在有意义的地方使用.你可以做更多的事情来抽象列表元素之和的概念.在Scheme中用函数编写函数更自然,这是一个完全不同的主题.这是一个简单的例子,但没有两个函数做同样的事情.