Mariav
Mariav

Reputation: 111

How to return a function in scheme (racket) using conditionals?

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

Answers (2)

Flux
Flux

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

&#211;scar L&#243;pez
&#211;scar L&#243;pez

Reputation: 236140

The cond expression in your code has some syntax errors:

  • There are brackets missing in each condition
  • You must not surround a procedure application with double brackets, this is a mistake: ((* 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

Related Questions