#scheme
#схема
Вопрос:
Я пишу процедуру, которая подсчитывает количество нулей в заданном списке. В этом списке может быть другой вложенный список. Алгоритм, который я придумал, был очень простым:
- Если текущий список равен нулю, верните 0
- Если текущий список является другим списком, вызовите подпрограмму для подсчета нулей в этом списке.
- В противном случае продолжайте обходить родительский список и подсчитывайте нули, если таковые имеются.
Тем не менее, я всегда получаю сообщение об ошибке,
=: expects type <number> as 2nd argument, given: quote; other arguments were: 0
и я понятия не имею, как это могло быть. Есть идеи?
Моя попытка была,
(define (helper lst)
(cond ((null? lst) 0)
((= 0 (car lst)) ( 1 (helper (cdr lst))))
(else ( 0 (helper (cdr lst))))))
(define (count-zeroes lst)
(cond
((null? lst) 0)
(else
(if (list? (car lst))
( (helper (car lst)) (count-zeroes (cdr lst)))
(if (= 0 (car lst))
( 1 (count-zeroes (cdr lst)))
( 0 (count-zeroes (cdr lst))))))))
(define ll '(0 1 2 0 '(1 0 0)))
(count-zeroes ll)
Спасибо,
Ответ №1:
Вам не нужен такой вспомогательный метод, как таковой. Метод count-zeroes может рекурсивно вызывать себя для car, если car является списком.
Вместо этого я бы выбрал что-то вроде этого
(define (count-zeroes lst)
(cond
((null? lst) 0)
((list? (car lst)) ( (count-zeroes (car lst)) (count-zeroes (cdr lst))))
((equal? (car lst) 0) ( 1 (count-zeroes (cdr lst))))
(else (count-zeroes (cdr lst)))
)
)
Комментарии:
1. Большое спасибо. Но не могли бы вы сказать мне, где я ошибся? Меня больше беспокоит ошибка, чем реальное решение, поскольку я практикуюсь со списком.
2. Я думаю, проблема в том, что ваш список определен как ‘(0 1 2 0 ‘(1 0 0)), когда все, что вам нужно, это ‘(0 1 2 0 (1 0 0)). В общем случае вам обычно не нужно более одной цитаты для списка.
3. Ах, я думаю, это может быть ваше использование = вместо equal?. При вызове (= 0 (car lst)), если (car lst) не является числом, вы получите эту ошибку, поскольку для = требуется 2 числа в качестве аргументов.
Ответ №2:
Прошло некоторое время с тех пор, как я практиковал scheme, но:
A) Я не думаю, что cddr
это правильная процедура в ( (helper (car lst)) (count-zeroes (cddr lst)))
— это должен быть просто cdr.
Б) Вам не нужна вторая вспомогательная функция — вы должны иметь возможность вызывать (count-zeroes car lst)
просто отлично, потому что в этот момент вы передаете список, который будет разделен так же, как был разделен его родительский элемент.
Таким образом, строка в споре будет ( (count-zeroes (car lst)) (count-zeroes (cdr lst)))
Комментарии:
1. Спасибо, что указали на это. На самом деле, я понял эту ошибку (cdr вместо cddr).