首页 > 解决方案 > 如何将此函数转换为内联调用

问题描述

我有以下函数来缩放(2-col)矩阵:

(define (scale-matrix matrix scale)
  (map (lambda (row)
         (list (* scale (car row))
               (* scale (cadr row))))
       matrix))

(scale-matrix '((1 2) (3 4)) 3)
; ((3 6) (9 12))                       

但是,我很难将其转换为内联咖喱调用。这是我目前所处的位置:

(map
 (lambda (row)
   (lambda (scale)
     (list (* scale (car row))
           (* scale (cadr row)))))
 '((1 2) (3 4)))
; (#<procedure:...esktop/sicp/021.scm:54:3> #<procedure:...esktop/sicp/021.scm:54:3>)

在这里传递比例和矩阵的正确方法是什么?换句话说,放在哪里3

到目前为止,我得到的最接近的是对其中的硬编码3

(map
 (lambda (row)
   ((lambda (scale)
      ; 3 hardcoded, nil placeholder. How to actually 'call' with 3?
      (list (* 3 (car row)) (* 3 (cadr row)))) nil)) 
 '((1 2) (3 4)))

或者,是否需要我传递scale作为第一个参数?它似乎以这种方式工作,但不确定是否需要这样做(甚至不确定为什么会这样!)

((lambda (scale)
  (map (lambda (row)
         (list (* scale (car row)) (* scale (cadr row))))
         '((1 2) (3 4)))) 3)

; ((3 6) (9 12))

标签: schemelispracket

解决方案


您的最后一次尝试是正确的:您必须在通话之外lambda提取used for 。你不能修改最里面的 lambda,期望一个带有一个参数的,你不能传递一个嵌套在那里。因此,如果您想咖喱,则别无选择,但是:scale mapmaplambdalambdascale

((lambda (scale)
   (map (lambda (row)
          (list (* scale (car row))
                (* scale (cadr row))))
        '((1 2) (3 4))))
 3)
=> '((3 6) (9 12))

至于它为什么起作用,就像任何其他匿名lambda电话一样。让我们看一个更简单的例子,这个:

(define (add1 n)
  (+ 1 n))

(add1 41)

评估时等效于:

((lambda (n)
   (+ 1 n))
 41)

顺便说一句,上面也是如何let扩展和评估 a 的:

(let ((n 41))
  (+ 1 n))

所以你也可以内联代码,如下所示;但是你为什么要咖喱呢?程序的原始代码是正确的。

(let ((scale 3))
  (map (lambda (row)
         (list (* scale (car row))
               (* scale (cadr row))))
       '((1 2) (3 4))))

推荐阅读