Scheme / Racket中的函数返回特定arities的函数

时间:2015-09-08 07:37:46

标签: lambda scheme racket variadic arity

如何在Scheme / Racket中定义一个返回特定arities函数的函数?

目前我的代码中包含以下内容:

(define (get-function n)
  (cond
    [(= n 1) (lambda (a) a)]
    [(= n 2) (lambda (a b) (+ a b))]
    [(= n 3) (lambda (a b c) (+ a b c))]
    ; and so on
    ))

当然它返回的函数的arity是n:

(procedure-arity (get-function 3)) ; returns 3

请不要介意“+”,在我的程序中它比“+”的折叠更复杂。但是,该函数的结构也可以递归地定义;类似于:

(define (get-function-variadic n)
  (lambda arguments
    (if (empty? arguments) 0
        (+ (car arguments)
           (apply (get-function-variadic (sub1 n)) (cdr arguments))))))

然后它返回可变函数:

(procedure-arity (get-function-variadic 3)) ; returns #(struct:arity-at-least 0)

这样所有这些都像普通Scheme的变量“+”一样工作:

((get-function-variadic 3) 1 2 3)

((get-function-variadic 3) 1 2)
((get-function-variadic 3) 1 2 3 4)

实际上我只希望第一个返回结果,而其他人则应该返回错误“错误的参数数量”。另外,在程序的其他部分,我依赖于生成的函数的arity。因此,可变参数函数不适合我(即使它检查“参数”的长度)。我需要一组由(get-function n)返回的不同整数arities的函数。是否可以在Scheme / Racket中定义?

1 个答案:

答案 0 :(得分:3)

这感觉就像一个XY问题,所以我不知道这对你有帮助,但是:

正如@Renzo评论的那样,如果您不需要在运行时执行此操作,则在编译时使用宏可能会更清晰,更快。

我不明白为什么你需要一个get-function-variadic来返回不是变量的函数。但是,我想您可以使用procedure-reduce-arity来获得示例中的预期结果:

#lang racket

(define (-get-function-variadic n)
  (lambda arguments
    (if (empty? arguments) 0
        (+ (car arguments)
           (apply (get-function-variadic (sub1 n)) (cdr arguments))))))

(define (get-function-variadic n)
  (procedure-reduce-arity (-get-function-variadic n) n))


(require rackunit)

(check-exn exn:fail:contract:arity? (λ () ((get-function-variadic 3) 1 2)))
(check-equal? ((get-function-variadic 3) 1 2 3) 6)
(check-exn exn:fail:contract:arity? (λ () ((get-function-variadic 3) 1 2 3 4)))