代码之家  ›  专栏  ›  技术社区  ›  Bwmat

方案中的“let”语法有问题

  •  1
  • Bwmat  · 技术社区  · 14 年前

    我正在学习“计算机程序的结构和解释”,做一个练习有点困难。( 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 回复  |  直到 14 年前
        1
  •  3
  •   law-of-fives    14 年前

    正如您的编辑所指出的,您过早地使用了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
  •  4
  •   Bwmat    14 年前

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

    另外,由于我使用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)))
    
        3
  •  2
  •   zakovyrya    14 年前

    试试这个:

    (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)))