Нарушение контракта с ракеткой (Макс. Функция рекурсии) - PullRequest
0 голосов
/ 08 июня 2018

Изучаем некоторую схему / ракетку, так что дайте мне немного свободы.

В настоящее время пытаюсь найти максимальное значение при заданном списке без использования встроенной функции max ().

ТекущийКод:

#lang racket
(provide max-num)
(define (max-num lst)
  (define (helper lst max)
    (displayln lst)
    (displayln max)
    (displayln " ")
    (when (null? max) ; first run
        (helper (cdr lst) (car lst)))
    (if (null? lst)
        max ; then end
        (if (> (car lst) max) ; else compare
            (helper (cdr lst) (car lst)) ; then update max
            (helper (cdr lst) max)))) ; else keep max
  (if (null? lst)
      #f ; then Error
      (helper lst '())) ; else run helper
  )

(max-num '())
(max-num '(1 5 2 4 3))

Вывод через DrRacket:

enter image description here

Насколько я могу судить, выходные данные displayln говорят мне, что яна правильном пути.Тем не менее, это в конечном итоге с нарушением договора реально?ошибка вместо того, чтобы возвращать максимальное значение.

Я предполагаю, что (if (null? lst)) не хочет возвращать "max" в конце и вместо этого перемещается к ветви else, несмотря на списокбыть пустымЯ искал и отлаживал около часа, но безрезультатно.Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 08 июня 2018

Вы должны знать, что когда вы делаете:

(when test
  do-something)
do-something-else

Это всегда будет do-something-else независимо от того, истинно test или нет.Итак, что происходит, так это то, что первый раунд max равен null?, и он делает (helper (cdr lst) (car lst))), и это возвращает ответ.Затем он отбрасывает этот ответ и продолжает до if с max, равным null?, и, в конце концов, терпит неудачу, когда делает (> (car lst) max), поскольку null? не является числом.В сообщении об ошибке говорится, что ожидалось real?, но оно получило начальное значение '().

Поэтому, чтобы намекать вам на дорогу, вы должны иметь одно выражение в дополнение к локальным определениямнапример.

(if test1
    result1
    (if test2
        result2
        alternative2))

или

(cond (test1 result1)
      (test2 result2)
      (else alternative2))

И, конечно, поскольку вы знаете, что аргумент не null?, вы можете просто позвонить (helper (cdr lst) (car lst)) вместо прохождения пустого списка и удалить when целикомwhen и unless предназначены для побочных эффектов и не совсем для хорошего функционального стиля Scheme.

...