如何正确计算Scheme中的成对差异?
给定一个数字列表,例如 (1 3 6 10 0)
,如何计算差异 (xi - xi-1 ),前提是 x-1 = 0 ?
(本例中的结果应该是 (1 2 3 4 -10)
)
我发现这个解决方案是正确的:
(define (pairwise-2 f init l) (first (foldl (λ (x acc-data) (let ([result-list (first acc-data)] [prev-x (second acc-data)]) (list (append result-list (list(f x prev-x))) x))) (list empty 0) l))) (pairwise-2 - 0 '(1 3 6 10 0)) ;; => (1 2 3 4 -10)
但是,我认为应该有更优雅但同样灵活的解决方案。 实在是太丑了。
我是函数式编程的新手,希望听到有关代码的任何建议。
谢谢。
Given a list of numbers, say, (1 3 6 10 0)
, how do you compute differences (xi - xi-1), provided that you have x-1 = 0 ?
(the result in this example should be (1 2 3 4 -10)
)
I've found this solution to be correct:
(define (pairwise-2 f init l) (first (foldl (λ (x acc-data) (let ([result-list (first acc-data)] [prev-x (second acc-data)]) (list (append result-list (list(f x prev-x))) x))) (list empty 0) l))) (pairwise-2 - 0 '(1 3 6 10 0)) ;; => (1 2 3 4 -10)
However, I think there should be more elegant though no less flexible solution. It's just ugly.
I'm new to functional programming and would like to hear any suggestions on the code.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
map
接受多个参数。 所以我会做如果你想把它包装在一个函数中,说
这当然不是小计划者的方式,而是避免自己编写递归的方式。 选择您最喜欢的方式。
map
takes multiple arguments. So I would just doIf you want to wrap it up in a function, say
This is of course not the Little Schemer Way, but the way that avoids writing recursion yourself. Choose the way you like the best.
我已经很久没有做过计划了,但这对我来说是一个典型的口语型小问题。
我从一个基本定义开始(请忽略括号的错误位置 - 我没有方便的方案解释器:
这处理 null 和atom 的垃圾情况,然后将肉情况委托给助手:
您可以使用“if”重写它,但我天生就使用 cond。
这里有两种情况:空列表 - 这很简单,还有其他一切。
对于其他所有内容,我抓住列表的头部并将此差异限制到递归情况下。 我认为事情并没有变得更简单。
I haven't done scheme in dog's years, but this strikes me as a typical little lisper type problem.
I started with a base definition (please ignore misplacement of parens - I don't have a Scheme interpreter handy:
This handles the crap cases of null and atom and then delegates the meat case to a helper:
You could rewrite this using "if", but I'm hardwired to use cond.
There are two cases here: null list - which is easy and everything else.
For everything else, I grab the head of the list and cons this diff onto the recursive case. I don't think it gets much simpler.
改进并适应 PLT 方案 plinth 的 代码,我认为近乎完美的解决方案是:
After refining and adapting to PLT Scheme plinth's code, I think nearly-perfect solution would be:
Haskell 告诉我使用
zip
;)Haskell tells me to use
zip
;)无论如何,一旦最短参数列表用完,映射就不会结束吗?
编辑:jleedev 告诉我,至少在一个方案实现中并非如此。 这有点烦人,因为没有 O(1) 操作来截断列表的末尾。
也许我们可以使用
reduce
:(免责声明:快速破解,未经测试)
Doesn't map finish as soon as the shortest argument list is exhausted, anyway?
edit: jleedev informs me that this is not the case in at least one Scheme implementation. This is a bit annoying, since there is no O(1) operation to chop off the end of a list.
Perhaps we can use
reduce
:(Disclaimer: quick hack, untested)
这是最简单的方法:
写出每个示例的代码扩展,看看它是如何工作的。
如果您有兴趣开始使用 FP,请务必查看如何设计程序。 当然,它是为编程新手编写的,但其中包含大量优秀的 FP 习惯用法。
This is the simplest way:
Write out the code expansion for each of the example to see how it works.
If you are interested in getting started with FP, be sure to check out How To Design Program. Sure it is written for people brand new to programming, but it has tons of good FP idioms within.