Лисп оценка конверсии в буквы - PullRequest
0 голосов
/ 01 октября 2018

Вопрос задан:

Define a LISP function SCORE->GRADE which takes a single argument, s, and returns a symbol according to the following scheme:
 s ≥ 90 A           73 ≤ s < 77 C+
 87 ≤ s < 90 A–     70 ≤ s < 73 C
 83 ≤ s < 87 B+     60 ≤ s < 70 D
 80 ≤ s < 83 B      s < 60 F
 77 ≤ s < 80 B–
 If the argument s is not a number then the function should return NIL.

Мой ответ таков:

 (defun SCORE->GRADE (s)
        (if (not (numberp s))  (return-from SCORE->GRADE “NIL”))
        (progn 
        (if (>= s 90) (return-from SCORE->GRADE "A"))
        (if (and (>= s 87) (< s 90)) (format nil “A-“))
        (if (and (>= s 83) (< s 87)) (format nil “B+”))
        (if (and (>= s 80) (< s 83)) (return-from SCORE->GRADE “B”))
        (if (and (>= s 77) (< s 80)) (return-from SCORE->GRADE “B-“))
        (if (and (>= s 73) (< s 77)) (return-from SCORE->GRADE “C+”))
        (if (and (>= s 70) (< s 73)) (return-from SCORE->GRADE “C”))
        (if (and (>= s 60) (< s 70)) (return-from SCORE->GRADE “D”)
        (if (< s 60) (return-from SCORE->GRADE “F”)) 
        )
      )
    )

Работает для 90, возвращает A, затем для всего остального выдает эту ошибку, с разными переменнымив отношении того, что я ввожу

*** - RETURN-FROM: переменная «B» не имеет значения

*** - ЕСЛИ: переменная «A-» не имеет значения

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

Я пробовал сообщение, формат t, случаи, некоторую работу дляв первые 3 случая, затем остановитесь.Не смог ничего понять.

Ответы [ 4 ]

0 голосов
/ 01 октября 2018

У меня была та же идея, что и у @ coredump.

(defun SCORE->GRADE (s)
  (cond ((not (numberp s)) nil)
        ((>= s 90) "A")
        ((>= s 87) "A-")
        ((>= s 83) "B+")
        ((>= s 80) "B")
        ((>= s 77) "B-")
        ((>= s 73) "C+")
        ((>= s 70) "C")
        ((>= s 60) "D")
        (t "F")))

Который снова может быть несколько более элегантно сформулирован как:

(defun SCORE->GRADE (s)
  (when (numberp s)
    (cond ((>= s 90) "A")
          ((>= s 87) "A-")
          ((>= s 83) "B+")
          ((>= s 80) "B")
          ((>= s 77) "B-")
          ((>= s 73) "C+")
          ((>= s 70) "C")
          ((>= s 60) "D")
          (t "F"))))
0 голосов
/ 01 октября 2018

когда вы исправили проблему с двойными кавычками, вот несколько дополнительных советов:

  • вам обычно не нужно использовать RETURN-FROM в Лиспе.
  • проверка несколькихусловия лучше всего выполнять с COND, а не с несколькими IF операторами.
  • функции типа >=, >, ... могут принимать более двух аргументов.

см. Например:

(cond ((not (numberp s)) NIL)
      ((>=    s 90)  "A" )
      ((>= 90 s 87)  "A-")
      ((>= 87 s 83)  "B+")
      ((>= 83 s 80)  "B" )
      ;...
      ((>= 60 s   )  "F" ))
0 голосов
/ 01 октября 2018

В дополнение к другим ответам обратите внимание, что в вашем случае вам не нужно дублировать общие границы, так как вы пытаетесь разделить оценки на оценки.

(cond
  ((>= s 90) "A")
  ((>= s 87) "A-")
  ((>= s 83) "B+")
  ...
  ((>= s 70) "C")
  ((>= s 60) "D")
  (t "F"))

Это также уменьшает количество инвариантов, которые вы должны сохранить в своем коде, что помогает в обслуживании.

0 голосов
/ 01 октября 2018

Кажется, что вы используете символ вместо " для переноса строк.

...