Как перейти во внутренний список в схеме?

#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).