转换为柯里化函数

Converting to a curried function

让我们采用以下 filter 函数:

#lang sicp

(define (filter function sequence)
  (if (null? sequence)
      nil
      (let ((elem (car sequence)) (rest (cdr sequence)))
        (if (function elem)
            (cons elem (filter function rest))
            (filter function rest)))))

(filter (lambda (x) (> x 3)) '(1 2 3 4 5))

以下是将其转换为柯里化函数的正确方法吗?

(define filter2
  (lambda (function)
    (lambda (sequence)
      (if (null? sequence)
          nil
          (let ((elem (car sequence)) (rest (cdr sequence)))
            (if (function elem)
              (cons elem ((filter2 function) rest))
              ((filter2 function) rest)))))))

也就是说,这两个区别是:

是否还有其他差异,或者更像是语法糖/在执行两者时括号中的差异?

是的,您的双 lambda 方法确实有效。但是也有更好的方法来做到这一点。

事实证明define可以直接做到这一点。下面两段代码是一样的:

(define f
  (lambda (x)
    (lambda (y)
      (+ x y)))

(define ((f x) y)
  (+ x y))

将此应用于上面的示例,我们得到:

(define ((filter function) sequence)
  (if (null? sequence)
      nil
      (let ((elem (car sequence)) (rest (cdr sequence)))
        (if (function elem)
            (cons elem (filter function rest))
            (filter function rest)))))

((filter (lambda (x) (> x 3))) '(1 2 3 4 5))

此外,如果您有一个现有的函数,您希望将其转换为柯里化变体,racket/function 模块提供 curry:

(require racket/function)

(define (f a b)
   (+ 1 2))

(((curry f) 1) 2)