Generally Lisp is less dogmatic about programming style. Some programming style might not be desirable in hand-written code, but might be useful for generated code. Since generated code (-> macros) is popular and well-supported in Lisp, programs may generate quite complex code.
Development process with refactoring
Often writing code is an evolutionary process with some refactoring. One thing I've done sometimes is this:
- write a longish and complex function
- identify the need to document parts of the code
- instead of conventional documentation -> extract parts of the code into named local functions with arglists. The name makes the purpose clear and the arglist is the interface
- if these local function look generally useful and will be reused -> extract them into global functions -> document and/or export them
We can think of various arguments for certain styles:
(the following lists are very likely not complete)
Flat global functions in a package, where only the relevant are exported and the local/helper functions are probably not exported and/or specially named.
Negative
- possibly many names in a package
- possibly more complex argument lists to pass in everything necessary
- need to keep them local in a package, possibly with special naming convention
- structure of the code might be more difficult to recognize, since dependencies are not visible based on lexical scope
Positive
- possibly more independent
- testing individual functions may be easier
- easy tracing / stepping of individual functions
- possibly easier to document
Unclear
- performance impact unclear
Global function with multiple local functions organized in some lexical scope
Positive
- variables in scope can be shared -> leads to shorter arglists
- dependencies better visible due to hierarchy of lexical scopes
- local functions can't be used outside of their intended scope -> information hiding
- functions may be easier to understand in context
Negative
- code gets more hierarchical -> looks more complex -> chance for new errors
- tools may not be able to trace or step local functions -> needs a Lisp with support for that when these tools might be necessary
- global function can get long
- maybe more difficult to test
- disassembly gets long, when looking at the machine code
- documentation makes the code even longer
- deep(er) indentation levels
- tool-based locating of the source code for a local function might be more difficult