1

In Common Lisp, we have to use the let form to declare a new lexically-scoped variable. This means that the code either looks like that written in C89 (all variables declared on top of scope), or acquires unreadably deep nesting. let* is somewhat useful, but is not always applicable.

Scheme 'solves' this problem by having a define form, that allows a lexical variable to be declared without creating a new nesting level.

So, the question is, is it possible to have Scheme-like variable declarations in Common Lisp, that do not increase the nesting level?

ndsrib
  • 19

2 Answers2

2

You don't have to use LET when using DEFUN: you can define local variables in the parameter list:

(defun foo (a)
  (let ((b (expt a 3)))
    (+ a b)))

is also

(defun foo (a &aux (b (expt a 3)))
  (+ a b))

That's not often seen in code, but it is a standard feature of Common Lisp.

Notice also that the syntax of LET and DEFUN is different in CL from what you are used to in Scheme: CL:LET allows declarations before the Lisp forms. CL:DEFUN allows documentation and declarations before the Lisp forms.

Note also that for example in Scheme R7RS small all internal DEFINE forms need to appear at the top of the enclosing form. Some Scheme implementations allow these forms to appear later in the body, but that is not in the R7RS small standard.

Disclaimer: This answer was written only using natural intelligence.

Rainer Joswig
  • 2,240
  • 13
  • 17
1

Yes, of course this is possible: CL is a language which excels in creating new languages: that's what Lisps are for.

You could start with something like binding. This is a macro which works so that

(binding
  ...
  (bind a 1)
  ...
  (bind b 2)
  ...))

Would expand to something like

(progn
  ...
  (let ((a 1))
    ...
    (let ((b 2))
      ...)))

and can bind local functions and so on.

This is a start but still requires wrapping the binding form around things. So for instance you need to write

(binding
  ...
  (bind a ...)
  (cond ((foo-p a)
         (binding ...))
        ...)
  ...)

And similarly in lots of cases. OK so you then write macros for variants of cond, defun, lambda & so forth such that they have bodies which are implicit bindings rather than implicit progns as they are in 'plain' CL. You call these macros, obviously cond &c and export them from your new CL/BINDING package which also reexports all the symbols from CL you do not wish to change.

Now you have a new language which does what you want.