Is the following how a let
statement resolves in terms of lambda
?
(let((a 4)(b 5)) (+ a b))
-->
((lambda (a b) (+ a b)) 4 5)
Is the general form something along the lines of:
(lambda (key1 key2 ...) <body> (val1 val2 ...))
-->
(let ((key1 val1) (key2 val2) ...) <body>)
What's the advantage of using the let
syntax? Is it just the easier readability placing the key/value pair next to each other?
Not only easier readability; it is easier to write code using let
than it is to write code that uses lambda
to express let
. Consider:
(let ((x 2)
(y 3))
(let ((u (+ x y))
(v (* x y)))
(display "let version:\n")
(for-each display (list x ", " y "\n" u ", " v "\n"))))
let version:
2, 3
5, 6
And a lambda
version of the same construct:
((lambda (x y)
((lambda (u v)
(display "lambda version:\n")
(for-each display (list x ", " y "\n" u ", " v "\n")))
(+ x y) (* x y))) 2 3)
lambda version:
2, 3
5, 6
Both versions work, but the let
version expresses intent through use of an appropriate syntax. The lambda
version expresses intent only through the semantics of its construction. If you are unaware if the idiom that allows the expression of the idea of let
binding, or if you can't piece together what is happening by analyzing the code, the meaning of the lambda
version is opaque. But the let
version clearly states its intent by using syntax dedicated to let
binding.
Further, as let
binding scenarios get more complex, using let
offloads a substantial portion of that complexity to the syntax. The above example is a simple nested let
, and it is already easy to make mistakes in the lambda
version. You have to be sure that the parentheses are placed correctly (I actually managed to get one out of place when writing the example code), and the final version places all of the variable identifiers at the beginning of the construction, with all of the bound values at the end. This means that to understand the lambda
version you must keep referencing the beginning and the end to understand what is happening in the body.
Generally speaking, lambda
expresses a very general idea, but let
expresses a more specific idea that is often needed. The advantage of let
syntax is that it allows you to express the more specific idea easily, concisely, and readably in a way that is less error-prone than always expressing the specific idea by implementing it in terms of the more general idea.