blob: 4af41bd2bd9ebb1aa1694595bc72085632a56697 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# No shadowing (shock!) and a reduced set of `let` forms
This may be shocking for Schemers but I believe shadowing variables is
evil. I've already written a bug once that would have been prevented
had it not been possible to shadow variables, and I don't even write
that much Scheme code.
And let's face it: The presence of four different forms by the name of
`let`, `let*`, `letrec`, and `letrec*` is daunting when you're coming
from another language. Lack of shadowing allows us to reduce this
without losing out much functionality.
In the absence of shadowing, `let` becomes nearly useless because you
can always use `letrec` to fulfill the same need; it's strictly more
powerful. (The only thing `let` can do that `letrec` can't, is to
refer to the previous binding of a variable before shadowing it.)
Further, the value of vanilla `letrec` is dubious when `letrec*` is
strictly more powerful. So, in Zisp, `let` is the ultimate binding
form that does what `letrec*` does in Scheme.
Except it does more! We haven't looked at the whole `let-values`
family yet. In Zisp, these are also merged into the ultimate `let`,
using the SRFI 71 syntax:
```scheme
(let ((a (one-value))
(b c (two-values))
((values d e . rest) (arbitrary-values)))
(do-things))
```
You may be wondering whether it also supports the "let loop" syntax of
vanilla Scheme `let` and the answer is no, because I hate that syntax.
It has too high a risk of leading to absolute spaghetti code with no
clear indication as to how the loop variables are being updated.
If you want to loop, use a dedicated looping syntax! Even `do` is
better than "let loop" shenanigans if you ask me.
|