Lisp变量不递增?
如果其他地方已经回答了这个问题,我提前表示歉意,但是我似乎找不到对我所遇到问题的详细解释。这也是我的第一篇文章,所以 基本上这是一个家庭作业,然而,我不是在寻找一个解决方案,因为我已经看到了一个这样的工作解决方案。坦白地说,我想实现我自己的解决方案,这样我就可以学习了,因为我对lisp/scheme非常感兴趣。其思想是计算列表中有多少个0或任何元素/原子,然后显示/返回 我确信通过查看代码,很容易看到我的逻辑在做什么。我遇到的问题是每次递归时增加totalZeros变量。(+5 myNum)肯定会在任何myNum的基础上增加5。因此,为什么(+1 totalzero)似乎不起作用?当我逐步通过调试器时,我可以看到totalZeros变量从未更改。它总是零Lisp变量不递增?,lisp,scheme,Lisp,Scheme,如果其他地方已经回答了这个问题,我提前表示歉意,但是我似乎找不到对我所遇到问题的详细解释。这也是我的第一篇文章,所以 基本上这是一个家庭作业,然而,我不是在寻找一个解决方案,因为我已经看到了一个这样的工作解决方案。坦白地说,我想实现我自己的解决方案,这样我就可以学习了,因为我对lisp/scheme非常感兴趣。其思想是计算列表中有多少个0或任何元素/原子,然后显示/返回 我确信通过查看代码,很容易看到我的逻辑在做什么。我遇到的问题是每次递归时增加totalZeros变量。(+5 myNum)肯定
(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)))
问题是这个表达式:
(+ 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/COD>是有用的,并且函数应该返回一个值,只有使用<代码>显示< /代码>才能在调用它之后打印该值。
上述方法可以解决问题,但没有利用现有的程序。事实上,解决问题的首选方法是重用现有功能。在Racket中,您只需调用count
过程,告诉它计算列表中找到的所有零:
(define (countZeros aList)
(count zero? aList))
(display (countZeros '(1 2 0 3 0 4 5 0 6 0 7 0 0)))
=> 6
(+1个全零)
将1
添加到totalZeros
中,但放弃结果。这就像说totalZeros+1而不指定它。您可以使用(setq totalZeros(+totalZeros 1))
或(incf totalZeros)
。您已经实现了一个递归解决方案(这是需要执行的函数),但递归函数没有返回任何内容。您应该从递归函数返回计数,而不是试图修改共享状态(这不是函数式操作)。@mbrach这似乎是scheme,set必须使用code>而不是setq
或incf
是的,我确实在使用Scheme,我应该更具体一些。。。非常感谢大家的评论。我的背景是C风格的语言。这绝对是一个大脑放屁。现在可以正常工作了。是的,你可以肯定地告诉我的代码有一个C风格的逻辑,因为背景是基于C的语言。我不知道为什么我认为(+1 totalzero)实际上是在用1存储和更新当前值。就像你说的,开始!工作完美,因为我使用的方案。总的来说,你的例子让我觉得很多东西都很有意思。我非常感谢你花时间发布你所做的事情。有一件事我不确定,使用if语句总是必须有一个else部分正确吗?所以为什么我用的时候。。。cond后面只需要一个语句?为什么不使用when而不是cond?@user2899772在Racketif
中必须有一个else
部分,如果您只需要一个条件,则必须使用when
。另一方面,cond
类似于一系列if-else-if-else
语句,并具有隐式begin
的额外好处,这意味着可以在每个条件下放置多个表达式。当
时,也是如此:您可以在其中放置多个表达式,而如果
时,将每个分支中的表达式限制为一个。