1

我现在正在学习 Lisp,我正在尝试做一个要求我获得列表最大值的练习,语法与我学过的大多数编程语言完全不同,所以我遇到了一些困难。

我的代码:

 (defun test(y)
     (cond
          ((and (first y) (> (second y)) (> (third y))) 
        (format t "numero maximo ~d" (first y))
          ((and (second y) (> (first y)) (> (third y))) 
        (t (format t "numero maximo ~d" (second y))
          ((and (third y) (> (second y)) (> (first y))) 
        (t (format t "numero maximo ~d" (third y))
    ))

我收到此错误:incomplete s-expression in region

4

2 回答 2

1

你的代码太复杂了,它试图从列表中获取元素,比较它们,然后打印一些东西。像在其他语言中一样,使用较小的函数,尤其是使用新语言时,经常进行测试以避免调试太大的东西。

您的代码使用 Emacs 自动缩进,如下所示:

(defun test(y)
  (cond
    ((and (first y) (> (second y)) (> (third y)))
     (format t "numero maximo ~d" (first y))
     ((and (second y) (> (first y)) (> (third y)))
      (t (format t "numero maximo ~d" (second y))
         ((and (third y) (> (second y)) (> (first y)))
          (t (format t "numero maximo ~d" (third y))
             ))

并且编辑抱怨括号不平衡:

  • (> (second y))中,>函数只给出一个参数
  • 您的所有cond子句实际上都嵌套在第一个子句中。使用突出显示匹配括号的编辑器在这里有很大帮助。语法应该是:

    (cond
      (test-1 ...)
      (test-2 ...)
      (t ...))
    

    如果您的测试涉及调用谓词,那么它看起来像:

    (cond
      ((and (f1 ...) (f2 ...)) ;; <-- test
       ... ;; <-- code
      ) ;; end of first clause
    ) ;; end of cond
    

    但请注意,您不需要为结束分隔符添加注释,缩进和括号的自动突出显示应该可以帮助您避免错误。

让我们尝试重写。

首先,您可以编写一个只比较数字的函数,而不考虑列表或格式;这是一个非常简单的max-of-3实现(没有作弊和调用内置max函数):

(defun max-of-3 (x y z)
  (if (> x y)
      (if (> x z) x z)
      (if (> y z) y z)))

评估函数,并在多个输入上对其进行测试,例如在 REPL 中:

CL-USER> (max-of-3 0 2 1)
2
....

然后,您可以为您的列表构建其他功能:

(defun test (list)
   (format t 
           "numero maximo ~d"
           (max-of-3 (first list)
                     (second list)
                     (third list))))

如果您需要提前进行更多错误检查,例如检查列表是否格式正确,您可能应该定义其他辅助函数。

于 2019-10-02T12:38:40.597 回答
0

如果我理解了问题和答案,无论列表的长度如何,我都可以提供一两个返回最大值的解决方案。因此,这些解决方案不限于三个列表。

这说明了一种测试“max-lst”是被测 Lisp 函数的方法:

(defconstant test-case 
  (list 1 2 0 8 7 6 9 4 5))

(defun run-test ()
  (max-lst test-case))

解决方案 1

此解决方案使用递归。如果你更喜欢循环,Lisp 有几个循环。不使用 Lisp 函数“max”:

(defun max-lst (lst-in)
  (cond ((null (second lst-in))
         (first lst-in))

        ((> (first lst-in) (second lst-in))
         (max-lst
          (list* (first lst-in) (rest (rest lst-in)))))

        (t
         (max-lst
          (list* (rest lst-in))))))
         

解决方案 2

如果你不反对使用 Lisp 函数“max”,这里有一个使用 max 的解决方案。

请注意, max 不限于两个参数。

(max 5 6 4 7 3)

将返回 7。

在这个解决方案中,函数“max”作为参数传递给函数“reduce”。“reduce”函数接受一个函数和一个列表作为参数。该函数应用于每对相邻的参数并返回结果。如果你想要总和,你可以传递 + 参数。

(defun max-lst-using-max (lst-in)
  (reduce #'max lst-in)) 

唉,我担心我提供这些解决方案为时已晚,无法与原始海报相关。但也许其他人会有类似的问题。所以,也许这会有所帮助,毕竟。

于 2020-08-06T03:02:11.357 回答