Racket(递归结构和处理模板)

Racket(递归结构和处理模板),racket,recursive-datastructures,mutual-recursion,list-processing,Racket,Recursive Datastructures,Mutual Recursion,List Processing,我在处理这个结构时遇到了麻烦,我想写一个函数,告诉我们在一次讨论中有多少个主题 ; a Discussion is (make-discussion String Digressions) (define-struct discussion [topic digressions]) ; Digressions is [ListOf Discussion] ; count-topics : Discussion -> Number ; counts the number of tot

我在处理这个结构时遇到了麻烦,我想写一个函数,告诉我们在一次讨论中有多少个主题

; 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)


我已经试了几个小时了,还没有解决。我不知道该怎么办,有人对球拍有敏锐的眼光吗?我已经尝试过先处理这个主题,但没有成功。您不应该在解决方案中使用
进行讨论,我们正在尝试遍历结构,而不是创建新的结构。有两种情况需要考虑:

  • 如果
离题列表为空,则我们找到了一个主题,没有其他地方可去
  • 否则,我们计算一个主题(当前主题),并对
    离题列表中的所有元素调用递归,添加它们的结果。使用
    apply
    map
  • 这就是我的意思:

    (define (count-topics d)
      (cond
        [(empty? (discussion-digressions d)) 1]
        [else (add1 (apply + (map count-topics (discussion-digressions d))))]))
    
    当然,您不需要使用
    apply
    map
    就可以解决这个问题,但为此,最好按照Alex的建议编写单独的过程。无论如何,我的方法正如预期的那样有效:

    (count-topics
     (make-discussion "music"
                      (list (make-discussion "politics" empty))))
    => 2
    

    有两种数据定义。一个用于
    讨论
    ,另一个用于
    离题
    ,它们是相互递归的。如果程序的结构遵循数据的结构,那么应该有两个函数,每个datadef一个,它们以与datadef相同的方式相互递归。代码中的一个“代码气味”在新构造的
    make discussion
    上重复出现,而不是在较小的数据子段上。在for structural recursion中,自然递归总是在原始数据的子块上,例如字段选择器的结果,而不是在这里构造的新结构上