 The do form consists of a body of statements which are all evaluated and executed in order. The do form itself returns the value of its last expression. What the do form effectively allows us to do is sneak sequential execution of multiple expressions into a context where only one expression is expected. The most obvious use case is with an if form. Here when Alice returns something other than false or nil, then we invoke bob, then carol returning the value of carol from the do and then in turn from the if. While a pure function could have mutable variables and still be pure, mutable local variables tend to make control flow logic harder to understand. Therefore, the variables we create in closure are immutable. They cannot be a reassigned new values after creation. The let special form creates local variables by binding values to symbols for the duration of a provided body. The journal form is let bindings body, where bindings is a series of symbols each followed by a value expression and the body is one or more expressions. Like a do form, a let form returns the value of the last expression in its body and like the parameters of an fn form, the bindings are written in a vector literal to distinguish them from the body. In this example, the value returned by a cult of food is bound to the symbol x and the value 3 is bound to the symbol y. The body of this let has two expressions, bar yx and baz x. In the body, the symbols x and y resolve to their locally bound values. So our let form here is effectively equivalent to this do form with the difference that this do form calls foo twice. Like fn forms, let forms are lexically scoped. This means that interior let and fn forms represent interior scopes in which their bindings take precedence over enclosing let and fn forms. Here, within the body of the interior let form, x resolves to its own binding of x rather than to the x of the enclosing let. Because the interior let has no binding for y, y in the interior let resolves to y of the enclosing let. In this example, we have a let form which binds a new function to the symbol x and the body of this let invokes the function with the argument 3. In the function itself, the single parameter is also named x and in the body of the function, we have another let form that binds 7 to x. So the three uses of x here all refer to a different x. Inside the interior let, x resolves to the value 7. Inside the function but outside the let, x refers to the parameter and then outside the function in the enclosing let, x resolves to the function itself. In principle, a language doesn't need any equivalent of a while loop or for loop because we can do any kind of iteration with recursive functions. A problem with recursive functions however is that each recursive call requires an additional frame on the call stack to store its local variables and the call stack isn't terribly large even on modern systems and so deeply recursive calls will easily lead to stack overflow. Consider though that when a function immediately returns the value of a recursive call, a smart compiler or interpreter could simply reuse the stack frame of the current call instead of creating a new one. Because the recursive call is guaranteed to be the last thing done in the function, all of the local variables of that call are no longer needed and so their memory can be simply reused for the recursive call. This trick is known as tail call elimination because it only works for recursive calls that are in so-called tail position of a function. While the compilers of some languages will automatically make this optimization, this is not the case in Clojure thanks to limitations of the Java virtual machine. Clojure does however let us make tail recursive calls explicitly with the recur special form. The recur special form which may only be used in tail position recursively calls the containing function by reusing the stack frame of the current call. Be clear that recurred needn't be used directly in the function body but rather may be nested further down in other forms which have their own bodies. As long as the compiler can ascertain that a recur will only be executed as the last expression of the function, the recur is considered to be in tail position. In this example each call to foo prints its arguments with the print function of closure.core and then foo makes a recursive call in which x has a value that is one greater and y has a value that is one lesser. So if we call foo with the values five and two we will see printed first five two then six one then seven zero then eight negative one then nine negative two then ten negative three and so on. Because each recursive call adds another frame on the call stack and because this function makes infinite recursive calls this function will eventually trigger a stack overflow. We can fix this problem though by simply replacing the call with recur. Now each recursive call reuses the same stack frame and so our function will recursively iterate forever without triggering a stack overflow. Again be clear that recur may only be used in tail position. This for example would be rejected by the evaluator. Now of course we generally don't want functions to recursively iterate forever. To prevent infinite recursion recur should be used conditionally in an if form like so. Here when x reaches the value nine the foo function will stop making additional recursive calls. You might not think that the recur is in tail position but tail position is transitive. Here the if form is in tail position of the function and the recur form is in tail position of the if form. Transitively then the recur form is in tail position of the function. Last thing to understand about recur when we have nested functions a recur form invokes the function in which it is most directly contained. So inside a nested function we cannot use recur to invoke an enclosing function.