常见的lisp中Nth的问题

时间:2011-09-09 03:36:11

标签: lisp common-lisp clisp

我正在尝试编写一个可以计算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 

2 个答案:

答案 0 :(得分:7)

修改

这似乎是一个很好的机会来强调一些常见的(小c)Lisp思想,所以我充实了我的答案来说明。


如另一个答案中所述,您可以使用sum函数对列表(数字)进行操作:

(defun sum (nums)
  (reduce #'+ nums))

点积是两个(等长)向量的乘法和:

(defun dot-product (x y)
  (sum (mapcar #'* x y)))

函数gpa是两者的简单组合:

(defun gpa (grades credits)
  (/ (dot-product grades credits) (sum credits)))

问题中的示例会产生我们期望的答案(减去格式化为浮点数):

(gpa '(3 3 4) '(1 2 1))
> 13/4

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

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

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

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

答案 1 :(得分:1)

如果您使用nth遍历列表,那么您做错了。在这种情况下,您可能想要编写求和函数:

(defun sum (items)
  (reduce #'+ items))