Henrik Andersson
Henrik Andersson

Reputation: 21

Rest argument , zero or one argument procedures in racket

I have this procedure:

(define count-calls
  (let ((count 0))
    (lambda char  
           (cond ((null? char) 
                  (begin(set! count (+ 1 count))
                        count))
                 ((eq? char 'how-many-calls) count)
                 ((eq? char 'reset) (set! count 0))))))

It does add 1 when (count-calls) is called but when I call (count-calls 'how-many-calls) it doesn't work as intended. I found that if you define (lambda (char) instead of (lambda char the (eq? ...) part is found but for (lambda char) it doesn't seem to recognize char.

Upvotes: 2

Views: 944

Answers (3)

uselpa
uselpa

Reputation: 18917

Extending stchang's answer, here's one way to solve this:

(define count-calls
  (let ((count 0))
    (case-lambda
      (() (set! count (+ 1 count)) count)
      ((char) (cond
                ((eq? char 'how-many-calls) count)
                ((eq? char 'reset ) (set! count 0) 'reset)
                (else 'wot?))))))

Upvotes: 1

Óscar López
Óscar López

Reputation: 236004

You have a couple of coding errors, this should fix them:

(define count-calls
  (let ((count 0))
    (lambda char
      (cond ((null? char) 
             (set! count (+ 1 count))
             count)
            ((eq? (car char) 'how-many-calls)
             count)
            ((eq? (car char) 'reset)
             (set! count 0))))))

In particular, notice that:

  • If a lambda's parameters are not surrounded by parenthesis (as is the case with char), then the procedure expects a list of arguments with variable size, possibly empty
  • With that in mind, it's clear why you need to do (car char) for extracting a parameter, if it was provided
  • It's not necessary to use a begin after a condition in cond, it's implicit

Use the procedure like this:

(count-calls)
=> 1
(count-calls 'how-many-calls)
=> 1
(count-calls 'reset)
=> 
(count-calls 'how-many-calls)
=> 0

Upvotes: 3

stchang
stchang

Reputation: 2540

If you dont have parentheses around the lambda parameters then you get all the arguments in a list. So your code is comparing 'how-many-calls to a list.

Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom]; memory limit: 8192 MB.
> ((lambda args (displayln args)) "a")
(a)
> ((lambda args (displayln args)) "a" "b")
(a b)
> ((lambda (args) (displayln args)) "a")
a
> ((lambda (args) (displayln args)) "a" "b")
#<procedure>: arity mismatch;
 the expected number of arguments does not match the given number
  expected: 1
  given: 2
  arguments...:
   "a"
   "b"

Upvotes: 3

Related Questions