как позаботиться о проверке состояния в Common lisp? - PullRequest
0 голосов
/ 20 февраля 2019

Просто изучал Common Lisp в течение нескольких дней, но профессор назначил мне упражнение.Тем не менее, мой код не может скомпилироваться. Может кто-нибудь показать мне, где я ошибся с моей частью кода? This is the question

(defun( MIN-2 a b)
(cond  
((and (numberp a) (numberp b) (<= a b)) a b)
((and (numberp a) (numberp b)    nil) ERROR)
)
)

Ответы [ 4 ]

0 голосов
/ 20 февраля 2019

Почему ваш код не работает

Может кто-нибудь показать мне, где я ошибся с моей частью кода?

(defun( MIN-2 a b)
(cond  
((and (numberp a) (numberp b) (<= a b)) a b)
((and (numberp a) (numberp b)    nil) ERROR)
)
)

Позвольте мне переформатировать ваш код (авто-отступ+ сжать скобки):

(defun (MIN-2 a b) ;; << bad syntax, as already pointed out in another answer
    (cond  
      ((and (numberp a) (numberp b) (<= a b))
       a
       b)

      ((and (numberp a) (numberp b) nil)
       ERROR)))

Исправим синтаксис defun:

(defun MIN-2 (a b)
    (cond  
      ((and (numberp a) (numberp b) (<= a b))
       a
       b)

      ((and (numberp a) (numberp b) nil)
       ERROR)))

Ошибка (я компилирую код в Emacs + SBCL):

Неопределенная переменная: ERROR

Действительно, error здесь свободная переменная.Вы должны указать это.

(defun MIN-2 (a b)
    (cond  
      ((and (numberp a) (numberp b) (<= a b))
       a
       b)

      ((and (numberp a) (numberp b))
       'ERROR)))

Предупреждение:

Удаление недоступного кода (ОШИБКА подчеркнута) .

Действительно, условие здесь является выражением and, где хотя бы одно выражение является NIL, что означает, что конъюнкция всегда ложна.Случай не может произойти, поэтому он был оптимизирован.

Кроме того, тест первого предложения:

(and (numberp a) (numberp b) (<= a b))

И тело предложения a, за которым следует b, что означает, что a оценивается, его значение отбрасывается (оно никогда не используется), затем b оценивается, и его значение является значением выражения cond: вы всегда возвращаете b, когда оба входа являются числами, такимичто a <= b.

Очевидно, это не то, что вы должны делать.Другие ответы уже охватывали хорошие решения.

Альтернативы

Я также здесь, чтобы предложить альтернативные, не обязательно домашние ответы:

Исключения для вылова

(defun min-2 (a b)
  (handler-case (if (<= a b) a b)
    (error () 'error)))

Исключения для вылова (бис)

(defun min-2 (a b)
  (or (ignore-errors (if (<= a b) a b))
      'error))

Использование общих функций

(defgeneric min-2 (a b)
  (:method ((a number) (b number)) (if (<= a b) a b))
  (:method (a b) 'error))
0 голосов
/ 20 февраля 2019

Дословный перевод:

(defun min-2 (a b)  ; Define a Lisp function MIN-2 … takes two arguments A and B
  (cond ((and (every #'numberp (list a b)) (<= a b)) a)  ; if … A <= B, returns A
        ((and (every #'numberp (list a b)) (> a b)) b)   ; if … A > B, returns B
        (t 'error)      ; if A or B is not a number (i. e. “else”), returns ERROR

Улучшение: проверьте числа только один раз.

(defun min-2 (a b)
  (cond ((not (every #'numberp (list a b))) 'error)
        ((<= a b) a)
        ((> a b) b)))

И, пожалуйста, сделайте отступ в своем коде и не оставляйте круглые скобки.

0 голосов
/ 20 февраля 2019

Я думаю, что стоит написать такие функции таким образом, чтобы было понятно, что такое проверка работоспособности и каковы фактические вычисления.Таким образом, в этом случае проверка работоспособности такова: «оба аргумента числа?»и вычисление - это сравнение их, если они есть.Поэтому разделите эти две вещи, а не объединяйте их в одно условие:

(defun min-2 (a b)
  (if (and (numberp a) (numberp b))
      ;; sanity check OK, so compare them
      (if (<= a b)
          a
        b)
    'error))

К сожалению, конечно, проверка работоспособности не адекватна:

> (min-2 1 2)
1

> (min-2 1 'a)
error

> (min-2 1 #c(1 1))

Error: In <= of (1 #C(1 1)) arguments should be of type real.

Упс: что такое проверка работоспособности должно быть, являются ли два аргумента действительными числами.К счастью, для этого есть предикат realp.Итак, правильная версия min-2:

(defun min-2 (a b)
  (if (and (realp a) (realp b))
      ;; sanity check OK, so compare them
      (if (<= a b)
          a
        b)
    'error))
0 голосов
/ 20 февраля 2019

Вы используете неверный синтаксис для определения функции.Используйте defun function-name (args)

(defun MIN-2 (a b)
(cond  
((and (numberp a) (numberp b) (<= a b)) a b)
((and (numberp a) (numberp b)    nil) ERROR)
)
)
...