2

当我执行以下操作时会发生什么?

(define ((func x) y)
    (if (zero? y)
        ((func x) 1)
        12))

我知道我可以这样做:

(define curried (func 5))

现在我可以使用咖喱了。我很好奇的是函数的定义。是否行

((func x) 1)

以 x 作为参数创建一个新的 lambda,然后在 1 上调用它?或者它是否比这更聪明,它只是重新使用现有的。(例如,如果我这样做(curried 0),该((func x) 1)行将等同于(curried 1)- PLAI Scheme 这样做吗?)

4

3 回答 3

8

在方案标准中规定

(define (f x) 42) is short for (define f (lambda (x) 42)) .

自然(非标准)概括意味着:

(define ((f x) y) (list x y)) is short for (define (f x) (lambda (y) (list x y)))
                which is short for (define f (lambda (x) (lambda (y) (list x y))))

为了测试它,让我们试试 DrScheme 中的例子

欢迎来到 DrScheme,版本 4.1.3.3-svn5dec2008 [3m]。语言:模块;内存限制:384 兆字节。

(定义((fx)y)(列表xy))(f 1)

((f 1) 2) (1 2)

如果我们命名临时值,可能更容易看出发生了什么:

(定义 h (f 1)) (h 2) (1 2) (h 3) (1 3)

由于“PLAI Scheme”是在 DrScheme 中实现的,我相信它继承了这个快捷符号。

于 2008-12-11T15:01:35.797 回答
2

自从我使用方案以来已经太久了,但是您可能会发现这篇文章很有帮助。它描述了两个宏 c-lambda 和 c-define 的实现,它们允许对 lambda 表达式进行隐式柯里化定义。

于 2008-12-10T20:03:51.910 回答
0

soegaard 的回答是正确的——这是传统的扩展。但是,drscheme 很聪明!

我发现以下代码在运行时间上是等效的:

原始来源:

(define ((substitute lv value) e)
  (cond [(LogicVar? e)
     (type-case LogicVar e
       [lv-any (id) (if (symbol=? id (lv-any-id lv))
                value
                e)]
       [lv-cons (f r) 
            (lv-cons ((substitute lv value) f)
                 ((substitute lv value) r))])]
    [(cons? e)
     (cons ((substitute lv value) (car e))
           ((substitute lv value) (cdr e)))]
    [else e]))

尝试优化:

(define (substitute lv value)
  (local ([define inner
        (lambda (e)
          (cond [(LogicVar? e)
             (type-case LogicVar e
               [lv-any (id) (if (symbol=? id (lv-any-id lv))
                    value
                    e)]
               [lv-cons (f r) 
                (lv-cons (inner f)
                     (inner r))])]
            [(cons? e)
             (cons (inner (car e))
               (inner (cdr e)))]
            [else e]))])
    inner))

大量使用此功能的代码(多次,而不仅仅是一次)在两个版本中的运行时间均为 1800 毫秒。更有趣的是,这个版本(我对正在发生的事情的可视化):

(define (substitute lv value)
  (local ([define inner
        (lambda (e)
          (cond [(LogicVar? e)
             (type-case LogicVar e
               [lv-any (id) (if (symbol=? id (lv-any-id lv))
                    value
                    e)]
               [lv-cons (f r) 
                (lv-cons ((substitute lv value) f)
                     ((substitute lv value) r))])]
            [(cons? e)
             (cons ((substitute lv value) (car e))
               ((substitute lv value) (cdr e)))]
            [else e]))])
    inner))

以 2000 毫秒运行。因此,如果在substitute 中对substitute 的调用都创建了一个lambda,那么肯定会减慢速度,但使用快捷表示法似乎并非如此。

于 2008-12-11T17:46:42.203 回答