DrRacket – 查找字符列表中的元音总数

DrRacket – Finding total number of vowels in list of characters

我正在初学者语言模式下使用 DrRacket。

代码如下:

(define vowels '(#\a #\e #\i #\o #\u))

(define total 0)

(define (any-in-list lst check)
  (cond
    [(empty? lst) (+ 0 total)]
    [(member? (first lst) check) (add1 total)]
    [else (any-in-list (rest lst) check)]))

(define (count-vowels string)
  (any-in-list (string->list string) vowels))

(count-vowels "how do i do this?")

total 值停留在 1。调试后,我意识到第 2 个 cond 语句的计算结果为 #true,然后停止。更新 total 值后,如何在列表的其余部分继续使用?

您在找到匹配项时忘记递归。
此外,由于 total 为 0,因此 (+ 0 total) 始终为 0,而 (add1 total) 始终为 1。

不要尝试使用全局变量和变异 - 递归并使用递归值。

(cond
    ; The empty list contains nothing, so the result is 0.
    [(empty? lst) 0]
    ; If the first element is a member, the result is
    ; one more than the count in the tail.
    [(member? (first lst) check) (add1 (any-in-list (rest lst) check))]
    ; Otherwise, the count is the same as in the tail.
    [else (any-in-list (rest lst) check)]))

molbdnilo 的回答解释了 OP 的问题并提供了正确的解决方案; 由于提到了“初学者语言”,因此可能值得 查看如何使用该方法构建解决方案 DrRacket 中的 BSL(初级学生语言)显然是针对它的。

按照 HtDF (How to Design Functions) 配方,可以编写以下内容 存根,包含签名 用途和“check-expect”示例:
(注意:布局与 HtDF 约定略有不同)

(define (count-vowels str)  ;; String -> Natural   ) *stub define* ;; *signature*
  ;; produce the count of vowel characters in str  ) *purpose statement*
  0 )                                              ) *stub body* (a valid result)

(check-expect (count-vowels "")   0 )              ) *examples*
(check-expect (count-vowels "a")  1 )              )
(check-expect (count-vowels "b")  0 )              )
(check-expect (count-vowels "ab") 1 )              )
(check-expect (count-vowels "ae") 2 )              )

第一个check-expect已经通过;现在写 inventorytemplate; count-vowels 必须对字符串中的每个字符做一些事情,但是没有 为此的标准 BSL 函数或模板。但是有一个做某事的模板 使用列表的元素:

(define (fn lox)  ;; (Listof X) -> Y               ) *template*
  (cond                                            )
    [(empty? lox) ... ]  #|base case|# ;; Y        )
    [else (...           #|something|# ;; X Y -> Y )
            (first lox) (fn (rest lox))) ]))       )

(define vowels (list #\a #\e #\i #\o #\u))         ) *inventory*
(member? x lox)     ;; X (Listof X) -> Bool        )
(string->list str)  ;; String -> (Listof Char)     )

因此 count-vowels 可以是 string->list 的组合,并具有由此派生的函数 模板,其存根、签名和 check-expect 是:

(define (count-vowels-in-list loc)  ;; (Listof Char) -> Natural
  0)
(check-expect (count-vowels-in-list          empty)  0 )
(check-expect (count-vowels-in-list (cons #\a '()))  1 )  ;; (+ 1 0)
(check-expect (count-vowels-in-list (cons #\b '()))  0 )  ;; (+ 0 0)
(check-expect (count-vowels-in-list (list #\a #\b))  1 )
(check-expect (count-vowels-in-list (list #\a #\e))  2 )

扩展模板并查看第一个 check-expect,|基本案例|可填写:

(define (count-vowels-in-list loc)  ;; (Listof Char) -> Natural
  (cond
    [(empty? loc) 0 ]
    [else (|something| (first loc) (count-vowels-in-list (rest loc))) ]))

对于接下来的两个 check-expects,(rest loc) 将是 '(),所以 (|something| #\a 0) => 1 但是 (|something| #\b 0) => 0
#\a 与 #\b 的区别在于 (member? #\a vowels) => #true 但是 (member? #\b vowels) => #false 所以 |something| 的描述性名称是 add-1-if-vowel:

(define (add-1-if-vowel chr n)  ;; Char Natural -> Natural
  (if (member? chr vowels)
      (add1 n)
      n))

所以按照这种系统化的设计方法开发出的完整解决方案是:

(define vowels (list #\a #\e #\i #\o #\u))

(define (add-1-if-vowel chr n)      ;; Char Natural -> Natural
  (if (member? chr vowels)
      (add1 n)
      n))

(define (count-vowels-in-list loc)  ;; (Listof Char) -> Natural
  (cond
    [(empty? loc) 0 ]
    [else (add-1-if-vowel (first loc) (count-vowels-in-list (rest loc))) ]))

(define (count-vowels str)          ;; String -> Natural
  (count-vowels-in-list (string->list str)))

(check-expect (count-vowels "")   0 )
(check-expect (count-vowels "a")  1 )
(check-expect (count-vowels "b")  0 )
(check-expect (count-vowels "ab") 1 )
(check-expect (count-vowels "ae") 2 )
(check-expect (count-vowels "how do i do this?") 5 )  ;; ^ (this is how :) ^