我的任务是使用fold-left或fold-right在Scheme中实现'map'函数和'filter'函数的最基本版本。我很难理解这些函数到底在做什么。以下是我的代码:
(define (myMap f l)
(fold-left (lambda (f a) (f a)) '() l))
(define (myFilter f l)
(fold-left f '() l))
下面的代码是我直觉上认为应该这样写的。对列表l中的每个元素应用一个过滤器(比如数字),并将结果放到空列表中。顶部的代码完全错误,但我感觉它更接近正确的方向。可以使用一种lambda函数来将该函数应用于一个数字。
以下是所需输出的示例:
(myMap sqrt '(4 9 16 25)) ; (2 3 4 5)
(myFilter odd? '(1 2 3 4 5)) ; (1 3 5)
map
和filter
不同,fold
不一定返回一个列表。折叠操作比map和filter更通用(正如可以通过fold来定义它们所证明的那样)。例如,使用它将列表(“reduce”是fold的常见替代名称)减少到总和可能更容易理解折叠的作用。尝试(fold-left + 0 '(1 2 3 4 5))
,看看我的意思。 - Alexis King(... (+ (+ (+ 0 1) 2) 3) ...)
这样应用,但我如何扩展它以执行任意函数?我猜想类似(lambda (f l n) (append (f n) l))
这样的东西,这样我就可以将我应用函数的元素添加回列表中?或者这样做没有意义? - amzafold
的过程的元素不是列表。您无法在非列表上调用append
。为了使fold
返回一个列表,您的累加器函数必须在每个累加步骤中显式执行构建新列表的职责。这就是折叠的含义:它是一种封装了遍历列表并将每个值复合到“累加器”值上的功能操作。累加函数接收当前累加器和新值,并生成一个新的累加器。 - Alexis King(... (+ 3 (+ 2 (+ 1 0))) ...)
,针对左折叠而言。并非所有的+
都是可交换的(a+b == b+a但a-b != b-a)。 - Will Nessmap
和filter
的实现。 - C. K. Young