方案中'let'语法的问题

时间:2010-09-08 03:08:51

标签: scheme sicp

我正在阅读“计算机程序的结构和解释”,我在进行其中一项练习时遇到了一些麻烦(2.1)。我正在以R5RS模式在DrRacket中编码。

这是我的代码:

(define (make-rat n d) 
  (let (((c (gcd n d))
         (neg (< (* n d) 0))
         (n (/ (abs n) c))
         (d (/ (abs d) c)))
        (cons (if neg (- n) n) d))))

这是DrRacket给我的错误信息:

let: bad syntax (not an identifier and expression for a binding) in: ((c (gcd n d)) (neg (< (* n d) 0)) (pn (/ (abs n) c)) (pd (/ (abs d) c)))

我想我已经搞砸了让我们的语法。但我不确定如何解决它。

3 个答案:

答案 0 :(得分:4)

我在变量声明周围添加了一组额外的括号,哎呀。

另外,由于我使用c来定义n和d,我不得不将let改为let *以使其正常工作

我的固定代码:

(define (make-rat n d) 
  (let* ((c (gcd n d))
         (neg (< (* n d) 0))
         (n (/ (abs n) c))
         (d (/ (abs d) c)))
        (cons (if neg (- n) n) d)))

答案 1 :(得分:3)

如您的编辑所示,您过早地使用了c标识符。 (这就是为什么在修复额外括号的语法问题后它无法正常工作。)“let”中的标识符彼此看不到。你需要在第一个下面嵌套你的第二个三个。

    (let ((c (gcd ...)))
      (let ((...))
        exps ...))

我不记得何时/如果SICP引入其他let表单,但是如果你使用了很多嵌套let,你可以使用let*,其中每个后续标识符都在以前的所有范围内。也就是说,以下两个定义是等价的:

(define foo
  (let* ((a 1)
         (b (+ 1 a))
         (c (+ 1 b)))
    (+ 1 c)))

(define foo
  (let ((a 1))
    (let ((b (+ 1 a)))
      (let ((c (+ 1 b)))
        (+ 1 c)))))

不幸的是,不同的let形式的范围规则对于初学者来说可能有点多。

答案 2 :(得分:2)

试试这个:

(define (make-rat n d)
  (let ([c (gcd n d)]
        [neg (< (* n d) 0)]
        [n (/ (abs n) c)]
        [d (/ (abs d) c)])
    (cons (if neg
              (- n)
              n) 
          d)))