Reputation: 111
How do I return a function using conditionals in scheme? What I want to do is to return the product of 2 numbers (when r = 0), or the sum (when r=1) or the difference (when r=2) or 0 (otherwise) depending on the value of r.
What I tried is below, but the return value is always 0. How do I fix that?
(define (f r)( lambda (x y)
(cond (equal? r 0)
((* x y))
( (equal? r 1)
( (+ x y)))
( (equal? r 2))
( (- x y))
(else
0 ))))
(( f 0) 2 3)
I would expect 6, but I get 0. Thanks in advance.
Upvotes: 0
Views: 1609
Reputation: 10950
cond
works like this:
(cond (test-expr then-body)
(test-expr2 then-body2)
(else then-body3))
The test-exprs are tested one by one, and the first test-expr that returns a non-false value causes its corresponding then-body to be executed. The last value in the executed then-body is the value of the whole cond
.
To know why you got 0
(and not 6
), look carefully at your first cond
clause: (cond (equal? r 0) ...)
. equal?
is the test-expr, and since equal?
itself is not false, its then-body is executed (i.e. r
and 0
are executed). Since 0
is the last value in the then-body, 0
is the value of the whole cond
. That's why you got 0
.
Note that nearly all lines in your cond
have parentheses that have been incorrectly placed. Here's a fixed version:
(define (f r)
(lambda (x y)
(cond ((equal? r 0) ; <- Parentheses fixed.
(* x y)) ; <- Parentheses fixed.
((equal? r 1) ; <- Parentheses fixed.
(+ x y)) ; <- Parentheses fixed.
((equal? r 2) ; <- Parentheses fixed.
(- x y)) ; <- Parentheses fixed.
(else 0))))
Here's an arguably better way to define the same function:
(define (f r)
(cond ((= r 0) *)
((= r 1) +)
((= r 2) -)
(else (lambda _ 0))))
For example:
((f 0) 2 3)
;; '(f 0)' returns '*', so this reduces to: (* 2 3)
;; Answer:
6
This version is technically better as it is not restricted to taking only two arguments. For example, you can now do this: ((f 1) 1 2 3 4 5 6)
(reduces to (+ 1 2 3 4 5 6)
).
Upvotes: 4
Reputation: 236140
The cond
expression in your code has some syntax errors:
((* x y))
Notice that you require to return an arithmetic procedure and, for example, we can simply return +
which is similar to returning (lambda (x y) (+ x y))
(except that it'll work for more than two parameters, but that's a win!).
Bear in mind that in Racket the solution can be written in a more concise way: for example, by using case
to simplify the conditions and const
for the last case, when we want to return a procedure that returns 0
no matter what are the parameters. Here's how:
(define (f r)
(case r
((0) *)
((1) +)
((2) -)
(else (const 0))))
It works as expected, by returning a procedure that you can apply to the given arguments:
((f 0) 6 7)
=> 42
((f 3) 2 3)
=> 0
Upvotes: 1