Lambda 特殊算术的Scheme/Racket返回函数中的函数

Lambda 特殊算术的Scheme/Racket返回函数中的函数,lambda,scheme,racket,variadic,arity,Lambda,Scheme,Racket,Variadic,Arity,如何在Scheme/Racket中定义返回特定算术函数的函数 目前,我的代码中包含以下内容: (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 )) 当然,它返回的函数的算术数是n: (procedure-arity (get-

如何在Scheme/Racket中定义返回特定算术函数的函数

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

(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
    ))
当然,它返回的函数的算术数是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)
所以所有这些都和普通模式的变量“+”:


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

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

正如@Renzo所评论的,如果您不需要在运行时执行此操作,那么在编译时使用宏执行此操作可能会更干净、更快

我不明白为什么需要一个
get function variadic
,它返回的函数是。。。不是可变的。但是,我认为您可以在示例中获得预期的结果:

#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)))

这是一个通过宏的解决方案。我设计它的时候仍然不知道(过程减少arity)函数(它比这个解决方案更通用)


这是a的典型任务,不是函数。@Renzo,我通过宏尝试了一下,见下文。看起来很有效。不过,正如格雷格所建议的,还有一个更好的选择。谢谢,@Greg,这正是我所需要的。不知何故,我错过了这个过程,减少了文档中的重复性。至于命名,我称它为“可变的”,因为它是可变的,我不能使它成为非可变的我通过宏进行了尝试,见下文。看起来很有效。然而,您的解决方案显然更好。
#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)))
(define-syntax-rule (variadic->fixed-arity f arguments ...)
  (lambda (arguments ...) (f arguments ...)))

(define-for-syntax tails (lambda (l) (if (null? l) (list l) (cons l (tails (cdr l))))))

(define-for-syntax n 10)

(define-syntax (variadic->fixed-arities-up-to-n stx)
  (syntax-case stx ()
    [(variadic->fixed-arities-up-to-n f)
     (let* ([arguments (generate-temporaries (build-list n values))]
            [arguments-sets (reverse (tails arguments))])
       #`(list
          #,@(map (lambda (arguments-set)
                    #`(variadic->fixed-arity f #,@arguments-set))
                  arguments-sets)))]))

(define (get-function-of-arity f n)
  (define functions-of-fixed-arities (variadic->fixed-arities-up-to-n f))
  (if (n . >= . (length functions-of-fixed-arities))
      (error "increase number of generated fixed-arities functions")
      (list-ref functions-of-fixed-arities n)))

(procedure-arity (get-function-of-arity + 7)) ; returns 7
(apply (get-function-of-arity + 7) (make-list 7 3)) ; returns 21