DrRacket / Scheme:合同违规,预计会有多少?

时间:2013-12-09 06:44:50

标签: scheme racket

所以我在方案中定义了3个函数,sumlist将列表中的所有数字相加,并且mean给出了列表的平均值。 mean2调用意味着并做同样的事情,但我得到一个错误。它说错误来自sumlist函数。

(define (sumlist lst)(if(null? lst)0 (+(car lst)(sumlist(cdr lst)))))
(define mean (lambda x(/(sumlist x)(length x))))
(define mean2 (lambda x(mean x)))

这就是我调用函数的方式

(mean 1 2 3 4 5)
=>3               ;it works

(mean2 1 2 3 4 5)
+: contract violation
expected: number?
given: '(1 2 3 4 5)
argument position: 1st
other arguments...:
0

我还是新手,上周刚刚介绍过它的方案,但这真的令人沮丧......我做错了什么?

1 个答案:

答案 0 :(得分:6)

因为(define (x . y) ...)(define x (lambda y ...))相同, identity的以下实现是相同的

(define (fun arg1)
  arg1)

(define fun 
  (lambda (arg1)
     arg1)

虽然list的以下实现是相同的

(define (fun . args)
  args)

(define fun 
  (lambda args
     args)

因此,当您应用(mean2 2 3 4 5) x时,列表为(2 3 4 5)(mean '(2 3 4 5))也会将所有参数包装到列表中,以便对sumlist的调用变为(sumlist '((2 3 4 5)))。在汇总表中,您尝试执行(+ '(2 3 4 5) 0),因为+期望数字作为参数而不是列表,因此无法工作。要解决此问题,您需要将mean2定义为以下之一:

;; Just make an alias to mean
(define mean2 mean)

;; wrap mean
(define (mean2 x) 
  (mean x))

;; use apply 
(define (mean2 . x)
   (apply mean x)) ; apply undoes list

我按照出现的顺序使用这些方法。有时使用apply是最好的,但如果你可以使用别名或换行则不行。