Reputation: 89
The following is the sample code i downloaded for the problem: A counter increments by one, modify it for passing as argument the value used for incrementing. E.g.,
(let ((c (create-counter))) (+ (c) (c) (c) (c))) => 6
(let ((c (create-counter 2))) (+ (c) (c) (c) (c))) => 12
Source code:
(define create-counter
(lambda ([num '()])
(let ((temp (lambda (incr)
(let* ((start (- incr))
(count start))
(lambda num
(set! count (+ incr count)) count)))))
(if (null? num)
(temp 1)
(temp num)))))
This is my own code:
(define create-counter
(let ([count 0])
(lambda ([x '()])
(cond
[(null? x) (set! count (+ 1 count)) (- count 1)]
[(> x 0)(set! count (+ x count)) (- count x)])
)))
I understand a bit briefly about let and lambda as for closures handle and such. However, for this extreme problem, i still have no idea how to write like the sample code. My code does the job to calculate with following example:
(+ (create-counter 2) (create-counter 2) (create-counter 2) (create-counter 2)) -> 12
However my code does not work with sample test cases. I sometimes get 0 or errors.
What would I have to modify my source code to able to run and work as the sample? Please help me to understand better in this scope and closures thingy and any tips would be very appreciate. Thank you and sorry for my bad english.
Upvotes: 0
Views: 109
Reputation: 18927
The code you downloaded is unnecessarily complicated.
Yours is better, but there's a confusion as to who gets the parameter which specifies the increment. create-counter
is a procedure that returns a procedure, but it's the first one you want to give the parameter to, not the second.
Also, why work with a default value of '()
when you can use a default value of 1? So your code becomes:
(define (create-counter (x 1))
(let ([count 0])
(lambda ()
(set! count (+ x count))
(- count x))))
By the way... instead of adding x
and subtracting x
again, you could just put the initial value of count
into a temporary variable and return that, or just use begin0
:
(define (create-counter (incr 1))
(let ((val 0))
(lambda ()
(begin0
val
(set! val (+ val incr))))))
or even shorter and with an option to set the initial value to something else than 0:
(define (create-counter (incr 1) (val 0))
(lambda ()
(begin0
val
(set! val (+ val incr)))))
Testing:
> (let ((c (create-counter))) (+ (c) (c) (c) (c))) ; => 6
6
> (let ((c (create-counter 2))) (+ (c) (c) (c) (c))) ; => 12
12
But this does not work for
(+ (create-counter 2) (create-counter 2) (create-counter 2) (create-counter 2)) ; -> 12
since here you expect create-counter
to return a numeric value, when indeed it returns a procedure.
Upvotes: 1