我想制作一个程序,破坏性地增加列表的奇数。我以为我会通过它来解决问题而只是使用'定车'!每当'奇怪?'是真的。
以下是代码:
+--------------+-----------+--------------+------------+
| Code_Project | Code_Name | Project_Name | GrandTotal |
+--------------+-----------+--------------+------------+
| 17-0004 | A | ABC | 3700 |
| 17-0004 | B | DEF | 1600 |
+--------------+-----------+--------------+------------+
我不确定为什么它不起作用,我想我不懂套装车!和set-cdr! 有人能解释一下吗谢谢。
答案 0 :(得分:1)
问题可能在于您的口译员,或者您定义程序的语言,或者您调用它的方式。例如,在DrRacket中,这很好用:
#lang r5rs
(define (test lst)
(cond ((null? lst) lst) ; this is the '() returned by the recursion
((odd? (car lst)) (set-car! lst (+ (car lst) 1))
(test (cdr lst)))
(else (test (cdr lst)))))
请记住,您的过程将返回空列表,因为这是递归的基本情况,这是一个尾递归过程,它返回基数的值案件作为最终结果。但不要担心,输入列表已就地修改,您可以在过程返回其值后进行检查。
(define lst (list 1 2 3 4))
(display (test lst))
=> ()
(display lst)
=> (2 2 4 4)
看看可变性如何令人困惑?一个过程返回一个值,但其输入已被修改并且现在具有不同的值。这是函数式编程(有利于不可变数据)更简洁易懂的原因之一,也说明了为什么在过程中改变输入参数是个坏主意;)
如果您绝对希望该过程返回变异列表,请按@ sepp2k建议,但请记住 - 输入列表已修改,实际上,与结果返回的列表相同:
(define (test lst)
(cond ((null? lst) lst)
((odd? (car lst)) (set-car! lst (+ (car lst) 1))
(test (cdr lst))
lst) ; add this line
(else (test (cdr lst)))))
亲眼看看:
(define lst (list 1 2 3 4))
(display (test lst))
=> (2 2 4 4)
(display lst)
=> (2 2 4 4)
答案 1 :(得分:1)
期待包含(2 2 4 4)的列表返回
您定义函数的方式,它将在空列表上调用时返回空列表,并在所有其他情况下返回递归结果。因此,由于唯一的基本情况是空列表,因此您将始终返回空列表。
如果要返回修改后的列表,则需要在递归后执行此操作。这是在(test (cdr lst))
之后,添加lst
以返回lst
的值。
答案 2 :(得分:1)
您使用set-car!
正确无误。以下是您告诉它的工作原理:
(define (test lst)
(cond ((null? lst) lst)
((odd? (car lst)) (set-car! lst (+ (car lst) 1))
(test (cdr lst)))
(else (test (cdr lst)))))
(define test-list (list 1 2 3 4))
(test test-list)
test-list ; ==> (2 2 4 4)
您希望函数返回修改后的列表是错误的。要做到这一点,您需要第一个递归步骤来返回参数。你需要把它包起来:
(define (inc-odds lst)
(define (test lst)
(cond ((null? lst) lst)
((odd? (car lst)) (set-car! lst (+ (car lst) 1))
(test (cdr lst)))
(else (test (cdr lst)))))
(inc-odds lst) ; do the stuff
lst) ; return the list
(inc-odds (list 1 2 3 4)) ; ==> (2 2 4 4)
(inc-odds '(1 2 3 4)) ; ==> "pigs flying"
注意最后一个。在RNRS up到R5RS中,将引用的文字传递给set-car!
会产生一个未定义的行为,这意味着任何事情都可以,因为从技术上讲,代码不是Scheme。在R6RS中,需要提出异常。