我正在构建地图功能作为练习。
我想出了以下代码:
#lang racket
(define (map procedure items)
(if (null? items)
empty
(cons (procedure (car items)) (map procedure (cdr items)))))
我试过这个并且工作正常:
(map add1 '(1 2 3))
>> '(2 3 4)
然后我尝试了这个,它也运行良好:
(define (scale-by-3 item)
(* 3 item))
(map scale-by-3 '(1 2 3))
>> '(3 6 9)
之后,我决定推广比例程序:
(define (scale-by-factor factor item)
(* factor item))
这种按比例缩放的功能有效:
(scale-by-factor 3 4)
>> 12
但是当我尝试将它与地图一起使用时:
(map (scale-by-factor 2 item) '(1 2 3))
我收到以下错误:
item: unbound identifier in module in: item
我该如何解决这个问题?有没有办法解决它没有lambda?
答案 0 :(得分:1)
失败是因为在您调用它时item
不存在 - 它在遍历列表时由map
作为参数传递。要解决这个问题,请执行以下操作:
(map (lambda (item) (scale-by-factor 2 item))
'(1 2 3))
或者我们可以使用curry
编写更好的替代方案,这会创建一个期望缺少lambda
参数的item
:
(map (curry scale-by-factor 2)
'(1 2 3))
答案 1 :(得分:0)
首先,item
确实没有约束。你没有在任何地方定义它。
您想要的是scale-by-factor
的部分应用。此函数接受两个参数并计算结果。但是如果你只在一个参数上部分应用它,它将评估一个接受另一个参数并计算最终结果的函数。
您可以使用Racket中的curry
来实现此目的,如here所示。
(define (map procedure items)
(if (null? items)
empty
(cons (procedure (car items)) (map procedure (cdr items)))))
(define (scale-by-factor factor item)
(* factor item))
(map (curry scale-by-factor 5) '(1 2 3))
由于this
,它被称为curry
答案 2 :(得分:0)
这里有很好的解决方案。我会提供一些替代方案,以便您可以看到更多方法来做同样的事情
您可以用咖喱形式定义scale-by-factor
功能
(define ((scale-by-factor x) y)
(* x y))
; note it needs two applications to get the computed result now
((scale-by-factor 3) 4)
; => 12
您可以在其他一个问题上使用CPS technique I showed you定义尾递归地图
(define (map f xs)
(let iter ([xs xs] [k identity])
(if (empty? xs)
(k empty)
(let ([v (f (car xs))])
(iter (cdr xs) (λ (rest) (k (cons v rest))))))))
(map (scale-by-factor 2) '(1 2 3))
; => '(2 4 6)
答案 3 :(得分:0)
在Racket中for/list
可用于创建地图功能:
(define (mymap proc lst)
(for/list ((item lst))
(proc item)))
(mymap add1 '(1 2 3))
; =>'(2 3 4)