for / fold Throwing Arity Mismatch Exception

时间:2017-12-11 19:26:42

标签: racket

我正在阅读Beautiful Racket一书。我正在尝试以功能性的方式创建我自己的语言,遵循“遵循语法:bf”一章。

我已将我认为的问题浓缩到以下程序中:

#lang racket

(define (fold-funcs control-list fruit-funcs)
  (for/fold ([current-list control-list])
            ([fruit-func (in-list fruit-funcs)])
    (apply fruit-func current-list)))

(define (driver)
  (define init-list (list))
  (display (fold-funcs init-list (list
                                  (lambda (lst) (cons "apple" lst))
                                  (lambda (lst) (cons "banana" lst))))))

当我在交互窗口(在DrRacket中)发出以下内容时:

(driver)

我希望得到以下内容:

'("banana" "apple")

事实上,我可以通过在Interactions窗口中发出以下内容来实现:

((lambda (lst) (cons "banana" lst)) ((lambda (lst) (cons "apple" lst))(list)))

但是,我实际上得到以下错误:

...arity mismatch;
 the expected number of arguments does not match the given number
  expected: 1
  given: 0

我知道这意味着什么。它说我试图执行一个程序,它需要一个参数而不提供该参数。但我看不出那是怎么回事。 fold-funcs被传递一个空列表作为累加器和一个函数列表,它们接受一个参数并返回一个列表。 (从技术上讲,利弊返回一对,但我检查了,以下返回#t:

(list? (cons "apple" (list)))

我想知道为什么上述程序不起作用。

1 个答案:

答案 0 :(得分:1)

近在咫尺,但误导apply。对于第一个近似,apply函数有两个参数:一个函数和一个列表。然后它将 1 函数应用于列表的参数,就像它们一次直接传入一样。

例如,以下两个代码块是等效的:

> (apply (lambda (x y) (+ x y)) '(1 2))
3

> ((lambda (x y) (+ x y) 1 2)
3

请注意,在一个案例中,我们是如何通过'列表' '(1 2),而在另一方中,我们将12作为单独的参数。

fold-funcs函数中,您正在使用apply:

(define (fold-funcs control-list fruit-funcs)
  (for/fold ([current-list control-list])
            ([fruit-func (in-list fruit-funcs)])
    (apply fruit-func current-list)))

假设current-list包含逐个传递给fruit-func的参数。但是,因为fruit-func期望单个参数,列表本身,您将得到一个arity不匹配。相反,如果您删除apply并直接致电fruit-func,则driver会按预期工作:

(define (fold-funcs control-list fruit-funcs)
  (for/fold ([current-list control-list])
            ([fruit-func (in-list fruit-funcs)])
    (apply fruit-func current-list)))

现在......

> (driver)
'(banana apple)

1 坏双关语,我知道......