Reputation: 183
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
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
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