; I would not recommend the following. Why not? (define vowel-1? (lambda (ch) (let ((num (char->integer (char-downcase ch)))) (or (eqv? num 97) (eqv? num 101) (eqv? num 105) (eqv? num 111) (eqv? num 117) )))) ; For numbers, use = rather than eqv? ; The conversion to numbers is overkill; you can compare individual characters. ; Hard to read: Do you know what 105 represents? ; May not work if you switch systems (there are different encodings) (define vowel? (lambda (ch) (let ((lc (char-downcase ch))) (or (char=? lc #\a) (char=? lc #\e) (char=? lc #\i) (char=? lc #\o) (char=? lc #\u))))) ; Warning! Taking substrings is a slow process. ; Better strategy: Use a counter variable to keep track of position in ; the string. (define tally-vowels-1 (lambda (str) (let ((len (string-length str))) ; The kernel counts the number of vowels in positions ; [pos..len). (let kernel ((pos 0)) (if (>= pos len) 0 (if (vowel? (string-ref str pos)) (+ 1 (kernel (+ pos 1))) (kernel (+ pos 1)))))))) (define tally-vowels-2 (lambda (str) ; The kernel counts the number of vowels in positions ; [0..pos]. (let kernel ((pos (- (string-length str) 1))) (if (< pos 0) 0 (if (vowel? (string-ref str pos)) (+ 1 (kernel (- pos 1))) (kernel (- pos 1))))))) (define tally-vowels-3 (lambda (str) (if (= (string-length str) 0) 0 (if (vowel? (string-ref str 0)) (+ 1 (tally-vowels-3 (substring str 1 (string-length str)))) (tally-vowels-3 (substring str 1 (string-length str))))))) ; Important lessons: ; * There are lots of ways to skin a cat or solve a problem. ; * Work with the actual type: Don't convert data types if you don't have to. ; * Sometimes it makes sense to recurse from the end rather than from the ; front, particularly for strings. ; * Document your kernels, at least a little, so that you remember what ; they're supposed to do (or so that the people helping you develop them ; know what you want them to do) ; * Consider the cost of your operations (substring is likely to be expensive). ; * The time thing is interesting