user2968401
user2968401

Reputation: 945

DrRacket/Scheme: Contract violation, number expected?

So I have 3 functions defined in scheme, sumlist adds up all numbers in a list, and mean gives me the mean of the list. mean2 calls mean and does the same thing, but i get an error. It says the error is coming from sumlist function.

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

This is how i call the functions

(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

I'm still new too scheme just got introduced to it last week, but it is really frustrating..what am i doing wrong?

Upvotes: 1

Views: 14554

Answers (1)

Sylwester
Sylwester

Reputation: 48745

Because (define (x . y) ...) is the same as (define x (lambda y ...)), the following implementations of identity are the same

(define (fun arg1)
  arg1)

(define fun 
  (lambda (arg1)
     arg1)

While the following implementation of list are the same

(define (fun . args)
  args)

(define fun 
  (lambda args
     args)

So when you apply (mean2 2 3 4 5) x is the list (2 3 4 5), and (mean '(2 3 4 5)) also wraps all arguments into a list so the call to sumlist turns into (sumlist '((2 3 4 5))). In sumlist you try to do (+ '(2 3 4 5) 0) which won't work since + expects numbers as arguments, not lists. To fix this you need to define mean2 as one of:

;; 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

I'd use the methods in the order of appearance. Sometimes using apply is the best but not if you can just alias or wrap.

Upvotes: 6

Related Questions