使用Let in Scheme

unj*_*nj2 10 lisp scheme

我想写一个程序来找到Scheme中二次方程的根.我使用LET进行某些绑定.

(define roots-with-let
  (? (a b c)
    (let ((4ac (* 4 a c))
          (2a (* 2 a))
          (discriminant (sqrt ( - (* b b) (4ac)))))
      (cons ( / ( + (- b) discriminant) 2a)
            ( / ( - (- b) discriminant) 2a)))))
Run Code Online (Sandbox Code Playgroud)

4ac 因为我不想要,我定义了判别式(* 4 a c).即使我已经定义(4ac (* 4 a c)),它给了我这个错误:

expand:模块中的未绑定标识符:4ac.

我的问题是如何评估(什么顺序)?如果我想要4ac,我let应该写另一个内心let?有一个更好的方法吗?

Jon*_*nas 31

let*而不是let.

let和之间的区别let*如下:

let*从左到右绑定变量.早期绑定可以用于进一步向右(或向下)的新绑定.

let 另一方面,可以将其视为简单lambda抽象的语法糖(或宏):

(let ((a exp1)
      (b exp2))
   exp)
Run Code Online (Sandbox Code Playgroud)

相当于

((lambda (a b)
    exp)
 exp1 exp2)
Run Code Online (Sandbox Code Playgroud)

  • 它(仅)关于评估顺序,它主要是关于范围.在plain let中,每个变量的范围只是表达式,而不是绑定.在let*中,每个变量的范围是表达式和​​每个绑定本身. (2认同)

Rai*_*wig 8

  • 4ac是一个带数值的变量,因此(4ac)没有意义.

  • LET绑定所有变量,但变量不能用于值的计算.

这不起作用:

(let ((a 1) (b 1) (c (* a b)))
   c)
Run Code Online (Sandbox Code Playgroud)

使用:

(let ((a 1) (b 1))
  (let ((c (* a b)))
    c))
Run Code Online (Sandbox Code Playgroud)

上面介绍了A和B的第一个LET.在第二个LET中,A和B现在都可用于计算C.

要么:

(let* ((a 1) (b 1) (c (* a b)))
   c)
Run Code Online (Sandbox Code Playgroud)