Is there a way to declare local variables in Lisp (avoiding let)?
let, lisp
Solution
Here's a proof of concept macro that pulls variable declarations from a flat list up into standard `let*` forms.
(defun my/vardecl-p (x)
"Return true if X is a (VAR NAME VALUE) form."
(and (listp x)
(> (length x) 1)
(eq 'var (car x))))
(defmacro my/defun (name args &rest body)
"Special form of DEFUN with a flatter format for LET vars"
(let ((vardecls (mapcar #'cdr
(remove-if-not #'my/vardecl-p body)))
(realbody (remove-if #'my/vardecl-p body)))
`(defun ,name ,args
(let* ,vardecls
,@realbody))))
Example:
(my/defun foo (a b)
(var x 2)
(var y 3)
(* x y a b))
(foo 4 5)
; => 120
Problem
I'm fond of Lisp, but one of the thing I find irksome about it is that it nests too much. In an imperative programming language, I can break a long expression by using an intermediate value, for instance: ``` int x = someFunctionCall() ? someOtherFunctionCall() : 42; int y = myUnterminableNameFunction(x); ``` instead of ``` int x = myUnterminableNameFunction(someFunctionCall() ? someOtherFunctionCall() : 42); ``` This can be done in Lisp too, but as far as I'm aware, only by using `let`. `let` introduces an additional level of nesting, which I'd rather avoid. I'm not looking to argue that opinion, but to find a way to declare local variable in a single, non-nesting function/macro call. Something like `declare_local` in the following: ``` (defun my_function (a b) (declare_local x (if (some_function_call) (some_other_function_call) 42)) (my_unterminable_name_function x)) ``` If it does not exist, can it maybe be implemented via a clever macro, without it being detrimental to performances?