Уловка, которую я выбрал из Essentials of Programming Languages, заключается в том, чтобы всегда писать рекурсивные функции списка, обрабатывая сначала два важных случая: null (конец списка) и не null.
Итак, базовая структура функции списка выглядит примерно так:
(define some-list-function
(lambda (list)
(if (null? list)
#f
(do-some-work-here (head list)
(some-list-function (tail list))))))
Обычно вы (1) проверяете на ноль (2) выполняете некоторую работу над головой и (3) возвращаетесь к хвосту.
Первое, что вам нужно сделать, это решить, какой ответ для пустого списка. Это либо #t, либо #f, но какие? Нулевой список имеет то же число a
, что и b
?
Далее вам нужно что-то сделать с рекурсивным случаем. Ваш базовый подход довольно хорош (хотя ваш пример кода неверен): ведите счет, который увеличивается, когда вы видите a
, и уменьшается, когда вы видите b
. Проблема в том, как отследить счет. Схема не имеет циклов *, поэтому вы должны делать все с помощью рекурсии. Это означает, что вам нужно передать дополнительную переменную-счетчик.
(define some-list-function
(lambda (list counter)
(if (null? list)
; skip null's code for a second
Теперь вы должны решить, является ли голова 'a
или нет, и увеличить count
, если это так (уменьшить в противном случае). Но здесь нет переменной count, она просто передается между функциями. Так как это сделать?
Ну, вы должны обновить его в строке, например:
(some-list-function (tail list) (+ 1 count))
Кстати, не используйте =
ни для чего, кроме цифр. Более новые, более прохладные Lisps позволяют это, но Схема требует, чтобы вы использовали eq?
для символов и =
для чисел. Так что для теста 'a
против 'b
вам понадобится
(if (eq? 'a (head tail)) ...)
; not
(if (= 'a (head tail)) ...)
Надеюсь, это поможет. Я думаю, что дал вам все кусочки, хотя есть несколько вещей, которые я пропустил. Вам нужно изменить нулевой регистр сейчас, чтобы проверить счетчик. Если это не = 0
в конце, ответ ложный.
Вы должны также поддерживать отдельную переменную flag, чтобы убедиться, что после переключения на 'b
вы вернете #f
, если увидите другой 'a
. Таким образом, список типа '(a a a b b a b b)
не пройдет по ошибке. Добавьте флаг так же, как я добавил counter
выше, добавив еще один параметр функции и передавая значение при каждом рекурсивном вызове.
Наконец, если ваш учитель действительно не оказывает вам никакой помощи, и не будет, тогда вы можете прочитать основную книгу по Схеме. Я сам не использовал ничего из этого, но слышал, что они хороши: Язык программирования схем , Как разрабатывать программы или ошибаться, я думал, что был третий Забронировать онлайн бесплатно, но я не могу найти это сейчас. Я думаю, если у вас много дополнительного времени и вы хотите поразить себя, вы можете прочитать Структура и интерпретация компьютерных программ . Он учит немного Scheme и много о языках программирования.
* У него есть некоторые из этих вещей, но лучше пока их игнорировать.