计算中的Curried函数的实现

时间:2008-12-10 19:48:44

标签: programming-languages scheme racket currying

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

(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是否执行此操作?)

3 个答案:

答案 0 :(得分:8)

在Scheme标准中,指定了

(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兆字节。

  

(define((f x)y)(list x y))   (f 1)

     

     

((f 1)2)   (1 2)

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

  

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

由于“PLAI Scheme”在DrScheme中实现,我相信它继承了这种快捷方式。

答案 1 :(得分:2)

自从我使用计划以来已经太久了,但您可能会发现this article很有帮助。 它描述了两个宏的实现,c-lambda和c-define,它们允许对lambda表达式进行隐式curried定义。

答案 2 :(得分: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毫秒。因此,如果替换内部的替换调用每个都创建一个lambda,那么肯定会减速,但看起来情况并非快捷符号的情况。