我是Racket的新手,我正在尝试编写一个带有数字n
的递归函数,并返回第一个n
整数的平方和。例如,(this-function 3)
返回14,因为14是9 + 4 + 1 + 0。
我尝试创建两个单独的函数,一个对每个数字进行平方并返回一个平方数字列表,另一个用于汇总列表。每个数字的平方函数是:
(define (squared my-list)
(cond [(empty? my-list) empty]
[(zero? my-list) 0]
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
如果我运行(squared 3)
,则返回(cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty))
。
当我运行第二个函数(sum函数)时:
(define (sum numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum (rest numbers)))]))
并运行(sum (squared 3))
我收到一条错误消息,因为(squared 3)
会在列表中返回一个额外的“缺点”。
我该如何解决这个问题?
答案 0 :(得分:1)
答案 1 :(得分:1)
squared
中的逻辑有点偏离。我将逐条解释问题。
[(empty? my-list) empty]
这没有任何意义,因为my-list
永远不会是一个列表。事实上,my-list
的名字很差。参数squared
需要的是数字,而不是列表。该条款可以完全删除。
[(zero? my-list) 0]
这是实际终止案例应该是什么,但它不应该返回0
。请记住,squared
必须返回列表,而不是数字。 此案例应返回empty
。
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
最后,这个条款太复杂了。您有正确的想法 - 将cons
新号码添加到列表的其余部分 - 但您需要进行太多次操作。请记住,(squared (sub1 my-list))
的结果本身就是一个列表,cons
的第二个参数是列表的其余部分。你不需要额外的缺点 - 你可以完全消除它。
结合这些变化,你得到了这个,它可以做你想要的:
(define (squared my-list)
(if (zero? my-list) empty
(cons (expt my-list 2)
(squared (sub1 my-list)))))
(我还将cond
替换为if
,因为不再需要cond
。)
那就是说,这段代码不是很划线。你有一个好主意将你的功能分解成两个函数 - 在函数式编程中,函数应该只做一个的事情 - 但你可以进一步分解它!具体来说,您可以利用Racket的内置高阶函数来使这类事物变得非常容易。
您可以通过恰当地合并map
和range
来替换整个squared
功能。例如,以下内容创建一个0-3的方块列表。
(map (curryr expt 2) (range 4))
(您需要致电(range 4)
,因为range
生成的列表从0变为n-1。)
接下来,您可以使用apply
轻松汇总列表。总结上面的列表,你可以这样做:
(apply + (map (curryr expt 2) (range 4)))
这为您提供14
的适当结果。显然,为了清楚起见,您可以将其封装在自己的函数中,但是一旦您学习了Racket的功能结构,上面的代码就会更清楚了。
(但是,我不确定你是否允许使用这些,因为你的问题看起来很像家庭作业。请注意以后的参考和完整性。)
答案 2 :(得分:0)
一个用于提供正方形列表的函数和一个用于对列表求和的函数不是必需的。 这将起到作用,并根据需要递归。
(define (my-sq n)
(cond [(zero? n) 0]
[else
(+ (* n n) (my-sq (- n 1)))]))
(my-sq 3) -> 14