I'm writing a function taking an interval as an argument and returns the percentage error but I stuck in the usage of let or let*. Here's the code:
nested let version:
(define (percent interval)
(let (start-point (car interval))
(let (end-point (cdr interval))
(let (center (/ (+ start-point end-point) 2)))))
(/ (- end-point center) center))
the error is: let: bad syntax (not an identifier and expression for a binding) in: start-point
let* version:
(define (percent interval)
(let* ((start-point (car interval))
(end-point (cdr interval))
(center (/ (+ start-point end-point) 2))))
(/ (- end-point center) center))
the error now is:
let*: bad syntax (missing body) in: (let* ((start-point (car interval)) (end-point (cdr interval)) (center (/ (+ start-point end-point) 2))))
I've referred to some documentation but couldn't figure out the mistake as well. (ps: I'm using DrRacket 6.2)
The final expression, the division itself, needs to go inside the let*
. This is because let
forms introduce bindings that are only lexically scoped to their bodies. Furthermore, let
forms require a body, which is why you're getting that error (in your example, they have no body at all because the final expression is outside them).
To fix this, just move the final expression within the let*
form:
(define (percent interval)
(let* ((start-point (car interval))
(end-point (cdr interval))
(center (/ (+ start-point end-point) 2)))
(/ (- end-point center) center)))
Your version using nested let
is slightly wrong in another way: you're missing a level of parens for each binding pair, which is causing the first error. That is, instead of this:
(let (start-point (car interval))
...)
...you need this:
(let ((start-point (car interval)))
...)
Note the extra parentheses. That said, the let*
version is much better! It's just a macro for nested let
forms that does the nesting automatically so you don't have to.
One more thing: if you're writing portable Scheme, all the parentheses need to be parentheses. If you're writing Racket, though, you can use square brackets interchangeably with parentheses. Because of this, idiomatic Racket uses square brackets in certain places as a stylistic choice to make the code more readable.
One of these cases is in let
binding pairs. Therefore, idiomatic Racket code would look like this:
(define (percent interval)
(let* ([start-point (car interval)]
[end-point (cdr interval)]
[center (/ (+ start-point end-point) 2)])
(/ (- end-point center) center)))
This just helps to make it more clear that each pair is creating a binding rather than calling a function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With