在 Lisp 中计算元音

问题描述 投票:0回答:1

试图更好地使用 Lisp,我遇到了以下问题:

(defun countVowels (string)
  (setf vowels (list 'a 0 'e 0 'i 0 'o 0 'u 0))
  (loop for ch across string
        when (member ch vowels)
        do (incf (getf vowels ch)))
  (format t "~{~a~^, ~}" vowels))

在我看来,这通过增加 plist 来计算每个元音。但是,当我使用例如

调用该函数时
(countVowels "test")

输出是

A, 0, E, 0, I, 0, O, 0, U, 0
lisp common-lisp
1个回答
0
投票

代码不正确。您正在符号列表中搜索字符。为了让它最低限度地工作,您需要将

vowels
初始化为

  (setf vowels (list #\a 0 #\e 0 #\i 0 #\o 0 #\u 0))

但是,它仍然存在一些问题。

setf
用于分配给现有变量,而不是创建新变量。虽然它将回退到创建变量,但 SBCL 对此发出了警告。我们应该使用
let
来代替,或者只是在
with
宏中使用
loop
块。

此外,命名约定只是在骗你。 Common Lisp 不区分大小写,因此

countVowels
COUNTVOWELS
,甚至
CoUnTvOwElS
之间没有区别。我们通常倾向于在 Common Lisp 中坚持一种情况,只是为了保持一致。

最后,没有令人信服的理由在函数内部进行打印。这只会夺走调用者的权力。相反,返回 plist,并让调用者决定如何处理它。如果你不想严重依赖

loop
宏,你可以写

(defun count-vowels (string)
  (let ((vowels (list #\a 0 #\e 0 #\i 0 #\o 0 #\u 0)))
    (loop for ch across string
          when (getf vowels ch)
          do (incf (getf vowels ch)))
    vowels))

(format t "~{~a~^, ~}" (count-vowels "test"))

或者你可以全力以赴

loop
并写作

(defun count-vowels (string)
  (loop with vowels = (list #\a 0 #\e 0 #\i 0 #\o 0 #\u 0)
        for ch across string
        when (getf vowels ch)
        do (incf (getf vowels ch))
        finally (return vowels)))

(format t "~{~a~^, ~}" (count-vowels "test"))
© www.soinside.com 2019 - 2024. All rights reserved.