【发布时间】:2013-02-03 01:37:40
【问题描述】:
我正在学习如何在方案中使用高阶函数。我得到了使用高阶函数的想法,但是我在使用它们时遇到了麻烦。对于这个学习练习,我宁愿只使用过滤器、折叠和/或映射的某种组合。
例如,我想构造两个列表之间的集合差异,分别称为 A 和 B。我将集合差异定义为 x,这样 x 是 A 的元素,但 x 不是 B 的元素。我只想使用函数映射、过滤和折叠。例如:
令 A = (1 8 6 2)
令 B = (5 7 9 1 6)
A 和 B 的集合差为 (8 2)
这个想法是通过遍历 A 的元素并查看 A 的元素是否等于 B 的元素来构造一个新列表,如果是,则不要将 a 添加到新列表中;否则将 a 添加到新列表中。
我的算法思路是这样的:
设 neq 为“不等于”
-
对于 A 中的每个 a 和 B 中的 b 计算表达式:
(neq? a b)对于 a = 1,我们有:
(和 (neq?1 5) (neq?1 7) (neq?1 9) (neq?1 1) (neq?1 6))
如果此表达式为真,则 a 进入新列表;否则不要将 a 添加到新列表中。在我们的示例中,
(neq? 1 1)的计算结果为 false,因此我们不会将 1 添加到新列表中。
我的整个过程几乎都依赖于 1,这就是我遇到麻烦的地方。
- 如何执行第 1 步?
- 我发现在第 1 步中我需要
map和fold函数的某种组合,但是如何分发and a neq b?
编辑这是我拥有的最接近的样本:
(fold-right (trace-lambda buggy (a b c) (and (neq? a b))) #t A B)
|(buggy 3 5 #t)
|#t
|(buggy 2 4 #t)
|#t
|(buggy 1 1 #t)
|#f
#f
上面显示了我的匿名函数尝试执行 (and (neq? a b)) 链的痕迹。但是,它只对 A 和 B 中相同位置/索引的元素执行此操作。
非常感谢所有帮助!
【问题讨论】:
-
fold将始终在 Scheme 中评估列表中的所有应用程序,并且不可能出现短路。ormapis a much better fit 在这里。fold-right的另一个缺点是不是尾递归(与fold-left不同)。 :) -
@WillNess:请参阅下面的答案,即可能发生短路。你只需要打电话/抄送。事实上,没有 call/cc 的严格函数式编程语言似乎漏掉了一些东西。
-
@Marc 可以。 :) 啊,非本地出口。当然,它改变了一切。不一定只是通过 call/cc BTW,在 Common Lisp 中有
return-from,或者只是go。
标签: list filter functional-programming scheme predicate