如果在其他地方已经回答了这个问题,我会提前道歉,但我似乎无法找到有关我所遇问题的详细解释。这也是我关于SO的第一篇文章......
基本上这是一项家庭作业,但是,我并不是在寻找解决方案,因为我已经在SO上看到过这方面的工作解决方案。坦率地说,我想实现我自己的解决方案,所以我可以学习,因为我非常有兴趣让我的头脑缠绕lisp / scheme。想法是计算列表中有多少0或任何元素/原子然后显示/返回。
我确信通过查看代码可以很容易地看到我的逻辑正在做什么。我遇到的问题是每次递增时增加totalZeros变量。 (+ 5 myNum)肯定会为myNum增加5。那么为什么不(+ 1 totalZeros)似乎工作?当我单步执行调试器时,我可以看到totalZeros变量永远不会改变。它总是零......
(define (countZeros aList)
(define totalZeros 0)
(define (iterator aList)
(let ((listSize (length aList)))
(if (> listSize 0)
(let ((tempVar (car aList)))
(when (eq? tempVar 0)
(+ 1 totalZeros))
(iterator (cdr aList)))
0)))
(let ((listSize (length aList)))
(when (> listSize 0)
(iterator aList))
(display totalZeros)))
答案 0 :(得分:3)
问题是这个表达式:
(+ 1 totalZeros)
在totalZeros
的值中添加一个,但随后对结果不做任何操作,因此它会丢失。您熟悉其他编程语言吗?上面的内容与C语言类似:
totalZeros + 1;
显然,如果您不在某处存储添加结果,则会丢弃该值。回到你的代码,如果你打算将加法存储在同一个变量中(就像totalZeros++;
表达式那样),这就是在Scheme中编写它的方法:
(set! totalZeros (+ 1 totalZeros))
事实上,通过使用上面的代码,您的代码将起作用。虽然可以用类似的程序风格编写正确的程序 - 定义一个局部变量并随意改变它的值,但不建议这样做。这对于类似C语言来说是正确的,但这不是你在Scheme中考虑解决方案的方式,通常你会将修改后的值作为参数传递给函数调用;这是一个等效的,更惯用的解决方案:
(define (countZeros aList)
(define (iterator aList totalZeros)
(cond ((null? aList)
totalZeros)
((zero? (car aList))
(iterator (cdr aList) (add1 totalZeros)))
(else
(iterator (cdr aList) totalZeros))))
(iterator aList 0))
(display (countZeros '(1 2 0 3 0 4 5 0 6 0 7 0 0)))
=> 6
注意null?
如何用于确定列表是否为空(而不是使用length
),并查看如何使用过程zero?
和add1
。注意totalZeros
计数器如何作为参数传递,如何在调用迭代器时将其初始化为0
,以及它在结束时如何返回列表为空时递归。还要注意当有几个条件需要考虑时cond
如何有用,以及函数应该返回一个值的事实,只有使用display
在之后打印该值&# 39; s叫。
以上将解决问题,但它没有使用可用的程序。实际上, 解决问题的首选方法是重用现有功能。在Racket中,您只需调用count
过程,告诉它计算列表中找到的所有零:
(define (countZeros aList)
(count zero? aList))
(display (countZeros '(1 2 0 3 0 4 5 0 6 0 7 0 0)))
=> 6