Why is it not allowed * by default?

As likely, all experienced edipers found at some point, the code is broken:

(let ((a 3) (b 4) (c (+ ab))) c) 

Use the let* form instead, referring to a single-binding variable in the binding clauses.

I'm just wondering - why is the default behavior seemingly wrong? Are there any risks when choosing always let* no matter how he uses it?

+4
source share
4 answers

I was taught that the reason is mostly historical, but it can still persist: since let performs parallel assignment, the lack of data dependency between variables can give the compiler flexibility for speed or space and compile something much faster than let* . I do not know how this works in the elisp compiler.

A little googling shows a similar question for Common Lisp: LET vs. LET * in Common Lisp

+6
source

Any forms of let* can be easily (and mechanically) expressed with let . For example, if we did not have a special form of let* , we could express

 (let* ((a 3) (b 4) (c (+ ab))) c) 

as:

 (let ((a 3)) (let ((b 4)) (let ((c (+ ab))) c))) 

On the other hand, some forms of let quite difficult, if possible at all, to express with let* . The following form of let cannot be expressed using let* without introducing an additional temporary variable or esoteric bitwise manipulation.

 (let ((xy) (yx)) ; swap x and y ...) 

So, in that sense, I think let more fundamental than let* .

+21
source

wrong to do it

 (let ((a 10) (ba)) <- error b) 

it is right:

 (let* ((a 10) (ba)) b) <- will evaluate to 10. 

The error in the first case is related to let semantics.

let* adds new characters to the existing environment, evaluating them internally.

let creates a new environment by evaluating new characters in the current envinronemnt, and the new environment will be deleted at the end of the evaluation of all new characters in order to evaluate the code (let () code).

let* is syntactic sugar for

 (let ((a xxx)) (let ((ba)) ...) 

while let syntactic sugar for

 ((lambda (a) ...) val_a) 

The second form is much more common , so maybe they thought to give it a shorter name ...

+4
source

I'm not sure what I would call let broken. For example, you may for some reason want to obscure a and b in a closed environment by defining c relative to the attached expression.

 (let ((a 11) (b 12)) (let ((a 3) (b 4) (c (+ ab))) ;; do stuff here will shadowed `a' and `b' c)) > 23 

As for the risks, I don’t know if they exist as such. But why create multiple nested environments when you don't need it? There may be a penalty for doing this (I don't have enough experience with elisp to say).

+2
source

All Articles