Racket (Рекурсивные структуры и шаблоны обработки)

Я в тупике при обработке этой структуры, я хочу написать функцию, которая сообщает, сколько тем возникает в обсуждении.

; a Discussion is (make-discussion String Digressions)
(define-struct discussion [topic digressions])

; Digressions is [ListOf Discussion]



; count-topics : Discussion -> Number
; counts the number of total topics in a discussion, including repeated topics

(define (count-topics d)
  (cond
    [(empty? (discussion-digressions d)) 0]
    [(cons?  (discussion-digressions d)) (add1 (count-topics (make-discussion (first (discussion-topic d))
                                                                                (list (make-discussion (rest (discussion-digressions d)))))))]))


(check-expect (count-topics  (make-discussion "music" (list (make-discussion "politics" empty)))) 2)

Я пытался несколько часов и еще не решил. Я не уверен, что делать дальше, у кого-нибудь есть острый глаз на Racket? Я попытался сначала обработать тему, но мне так и не удалось.

1 ответ

Вы не должны использовать make-discussionв вашем решении мы пытаемся обходить структуры, а не создавать новые. Следует рассмотреть два случая:

  • Если digressions список пуст, значит, мы нашли одну тему, и больше некуда идти.
  • В противном случае мы считаем одну тему (текущую) и вызываем рекурсию по всем элементам в спискеdigressions, добавляя свои результаты. Это легко реализовать, используяapply а также map

Это то, что я имею в виду:

(define (count-topics d)
  (cond
    [(empty? (discussion-digressions d)) 1]
    [else (add1 (apply + (map count-topics (discussion-digressions d))))]))

Конечно, вы можете решить эту проблему, не используя apply а также map, но для этого лучше писать отдельные процедуры, как предлагает Алекс. Во всяком случае, мой подход работает так, как ожидалось:

(count-topics
 (make-discussion "music"
                  (list (make-discussion "politics" empty))))
=> 2
Другие вопросы по тегам