2015-08-24 2 views
3

Я пишу функцию, принимающую интервал в качестве аргумента, и возвращает процентную ошибку, но я застрял в использовании let или let *. Вот код:Использование вложенных let или let * в схеме

вложенная версия пусть:

(define (percent interval) 
    (let (start-point (car interval)) 
    (let (end-point (cdr interval)) 
     (let (center (/ (+ start-point end-point) 2))))) 
    (/ (- end-point center) center)) 

ошибка: пусть: плохой синтаксис (не идентификатор и выражения для связывания) в: начальной точке

пусть * версия:

(define (percent interval) 
    (let* ((start-point (car interval)) 
    (end-point (cdr interval)) 
    (center (/ (+ start-point end-point) 2)))) 
    (/ (- end-point center) center)) 

ошибка сейчас:

let*: bad syntax (missing body) in: (let* ((start-point (car interval)) (end-point (cdr interval)) (center (/ (+ start-point end-point) 2)))) 

Я ссылался на некоторую документацию, но не мог понять и ошибку. (пс: Я использую DrRacket 6.2)

+0

Вы упомянули, что используете DrRacket. Используете ли вы язык Racket, один из языков Scheme (R5RS или R6RS) или один из языков обучения? –

+0

Я использую Scheme, но не Racket строгий суперсет из Схемы? – Caesar

+0

Не совсем, плюс различные диалекты все немного разные.Обычно бывает полезно указать * точно * какой вариант схемы, с которой вы работаете, ни одна из них не является одинаковой. –

ответ

6

Окончательное выражение, само деление, нужно идти внутриlet*. Это связано с тем, что формы let вводят привязки, которые лексически охватывают их тела. Кроме того, let формы требуют тела, поэтому вы получаете эту ошибку (в вашем примере у них нет тела вообще, потому что окончательное выражение вне их).

Чтобы это исправить, просто переместить окончательное выражение в виде: let*

(define (percent interval) 
    (let* ((start-point (car interval)) 
     (end-point (cdr interval)) 
     (center (/ (+ start-point end-point) 2))) 
    (/ (- end-point center) center))) 

вашу версию с помощью вложенной let немного неправильно по-другому: вы теряете уровень скобок для каждой пары связывания, который вызывает первую ошибку. То есть, вместо этого:

(let (start-point (car interval)) 
    ...) 

... Вам нужно это:

(let ((start-point (car interval))) 
    ...) 

Примечание дополнительные скобки. Тем не менее, версия let* намного лучше! Это всего лишь макрос для вложенных форм let, которые автоматически вставляют вложенность, поэтому вам не нужно.

Еще одна вещь: если вы пишете переносную схему, все круглые скобки должны быть скобки. Однако, если вы пишете Racket, вы можете использовать квадратные скобки взаимозаменяемо с круглыми скобками. Из-за этого, идиоматическая Racket использует квадратные скобки в определенных местах как стилистический выбор, чтобы сделать код более читаемым.

Один из этих случаев находится в let связующих парах. Поэтому, идиоматических код Ракетка будет выглядеть следующим образом:

(define (percent interval) 
    (let* ([start-point (car interval)] 
     [end-point (cdr interval)] 
     [center (/ (+ start-point end-point) 2)]) 
    (/ (- end-point center) center))) 

Это просто помогает сделать его более ясным, что каждая пара создает связывания вместо вызова функции.

+0

Большое спасибо. Теперь я это делаю. В Racket вложенное let, безусловно, намного сложнее, чем let *, однако в MIT Scheme в структуре let дополнительные скобки не ищут незаменимым. – Caesar

+0

Квадратные скобки совпадают с круглыми скобками в схеме R6RS, поэтому код идиоматической ракетки совместим. – Sylwester

+0

Получил это. :) Благодаря. – Caesar

Смежные вопросы