如何在 CCHICKEN 中实现可选参数



我是 CHICKEN 和 Scheme 的新手。在我寻求理解尾递归的过程中,我写道:

(define (recsum x) (recsum-tail x 0))
(define (recsum-tail x accum)
  (if (= x 0)
      accum
      (recsum-tail (- x 1) (+ x accum))))

这符合我的预期。但是,这似乎有点重复;有一个可选参数应该使它更整洁。所以我尝试了:

(define (recsum x . y)
  (let ((accum (car y)))
    (if (= x 0)
        accum
        (recsum (- x 1) (+ x accum)))))

但是,在 CHICKEN(也许在其他方案实现中(,car不能用于()

Error: (car) bad argument type: ()

有没有另一种方法来实现可选的函数参数,特别是在 CHICKEN 5 中?

我认为您正在寻找一个命名的let,而不是可选的过程参数。这是一种使用(可能(额外参数定义帮助程序过程的简单方法,您可以根据需要初始化这些参数:

(define (recsum x)
  (let recsum-tail ((x x) (accum 0))
    (if (= x 0)
        accum
        (recsum-tail (- x 1) (+ x accum)))))

当然,我们也可以使用 varargs 实现它 - 但我认为这看起来并不优雅:

(define (recsum x . y)
  (let ((accum (if (null? y) 0 (car y))))
    (if (= x 0)
        accum
        (recsum (- x 1) (+ x accum)))))

无论哪种方式,它都可以按预期工作:

(recsum 10)
=> 55

Chicken 有可选的参数。你可以这样做:

(define (sum n #!optional (acc 0))
  (if (= n 0)
      acc
      (sum (- n 1) (+ acc n))))

但是,我将投票反对使用它,因为它是非标准方案。鸡说他们支持 SRFI-89:可选的位置和命名参数,但它似乎是早期版本,鸡蛋需要重做。无论如何,当它被重新应用时,这应该可以工作:

;;chicken-install srfi-89 # install the egg
(use srfi-89) ; imports the egg
(define (sum n (acc 0))
  (if (= n 0)
      acc
      (sum (- n 1) (+ acc n))))

你使用休息参数的想法也有效。但请记住,该过程随后将在每次迭代的堆上构建一个pair

(define (sum n . acc-lst)
  (define acc 
    (if (null? acc-lst) 
        0 
        (car acc-lst)))
  (if (= n 0)
      acc
      (sum (- n 1) (+ acc n))))

所有这些都泄露了内部信息。有时,具有可选参数是公共合约的一部分,但在这种情况下,这是为了避免多写几行。通常你不希望有人传递第二个参数,你应该保持内部的私密性。更好的方法是使用命名let并保持公共合同不变。

(define (sum n)
  (let loop ((n n) (acc 0))
    (if (= n 0)
        acc
        (loop (- n 1) (+ acc n))))

相关内容

  • 没有找到相关文章

最新更新