用球拍建筑地图

时间:2016-10-19 00:51:30

标签: functional-programming lisp racket sicp

我正在构建地图功能作为练习。

我想出了以下代码:

#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?

4 个答案:

答案 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)