Brett
Brett

Reputation: 183

If statements in Racket

I am trying to construct a function "number-crop" which takes three arguments x a b. If x is to the left of the closed interval [a, b] on the number line, then return a. If x is to the right of the interval, then return b. Otherwise, just return x. This is what I have:

(define (number-crop x a b)
  (if (max x a b) x b)
  (if (min x a b) x a))

I am returned with the error, "define: expected only one expression for the function body, but found 1 extra part". I am new to Racket so I am still trying to understand how if statements work within the language.

Upvotes: 3

Views: 4686

Answers (2)

Alexis King
Alexis King

Reputation: 43842

Scheme/Racket if expressions always have exactly one condition and exactly two branches. Since they are expressions, not statements, this makes them very useful, and they function much like the conditional “ternary” operator in languages in the C family. However, when you have multiple conditions, you likely want something closer to if...else if chains, which is provided via the cond form.

The cond form is just like if, except with the ability to have any number of “clauses” which are each determined by a single condition. Using cond, your number-crop function would look like this:

(define (number-crop x a b)
  (cond
    [(< x a) a]
    [(> x b) b]
    [else    x]))

(Note that else is special inside of cond—it replaces the condition for the last clause, and it always runs if the other cases fail.)

This would likely work, but if you already have access to min and max, you don’t actually need to branch at all! If you use those two functions together, you can write number-crop with neither if nor cond:

(define (number-crop x a b)
  (min (max a x) b))

This works because composing both min and max will effectively clamp the value within the given range, provided that a is always the minimum and b is always the maximum.

Upvotes: 5

Diego Sevilla
Diego Sevilla

Reputation: 29011

In Scheme (Racket), functions are defined to return one thing. In your case it is clear: the result of the operation you describe. However, Scheme is different from most imperative languages in several respects. For example, if you look at your expression inside the define, it contains two expressions, one after the other. This contradicts the "one expression that calculates the function" assumption in Scheme.

Moreover, even if you write it in an imperative language, you'd use nested ifs, that you can of course use here. Something along the lines of:

(define (number-crop x a b)
  (if (= x (max x a b))
      b
      (if (= x (min x a b))
          a
          x)))

Upvotes: 3

Related Questions