GreenSpunning is the
ad hoc implementation of domain-independent language features in a language which lacks the feature; it can range from a simple one-line function or macro to the canonical description of
GreenSpunning: a "half-assed implementation of half of
CommonLisp''.
There are several levels of
GreenSpunning to consider; some may object to calling these
GreenSpunning. Note: It is assumed that the emulated feature may come from any language; not just Lisp.
Greenspunning typically does not refer to third-party libraries which are not part of the definition of a particular language, but which are widely available, of high quality, and generally considered part of the programmer's toolkit. Instead, the term should be reserved for instances of
ReinventingTheWheel.
Level 0: The Features Are Already There
No work needs to be done apart from using them.
Level 1: By Convention
A feature is "implemented" by some convention on how to use another feature; for example, imitating Java interfaces in C++ by use of classes which contain nothing but
PureVirtual methods. Many
DesignPatterns are actually instances of Level 1
GreenSpunning. See
AreDesignPatternsMissingLanguageFeatures.
Level 2: One-liners
A language feature is trivially implemented on top of another language feature, by use of a simple class, function, or macro, often containing just one or a few lines of code.
Level 3: As a Library
The language feature is implemented as non-trivial library of functions, classes, macros, etc., with the restriction that the implementation is portable. Often times, such libraries get added to the language definition, in which case claims of
GreenSpunning may then vanish, if done well. The majority of such libraries are, however,
ad hoc and half-assed. Many home-brew collection class libraries are of this sort. (See
IhadToWriteMyOwnLinkedList.)
Level 4: Dirty tricks
Similar to the above case, but
UndefinedBehavior is invoked in order to implement the feature. All
GarbageCollection libraries for C/C++ are in this category -- for them to function properly they need incestuous knowledge of the compiled code and the target platform. Porting such a library to a new target often involves more effort than a recompile. Use of
PointerCastPolymorphism to implement OO in
CeeLanguage is another popular example, although the dirtiness is from the need for programmer discipline rather than from
UndefinedBehavior in that case.
Level 5: MetaProgramming
Some external tool is used to generate code in the target language from a specification in some augmented form, or a higher-level language. This is
not GreenSpunning when done as a clean
DomainSpecificLanguage;
GreenSpunning refers to the domain-independent case done in an
ad hoc manner. A classic example would be a homebrew system for
RemoteProcedureCall that worked in the same manner -- taking an interface definition file and spitting out stubs/skeletons in the target language. (Again, use of industry-standard tools like CORBA or "real" RPC is not Greenspunning). Another example: implementing
LispLanguage in
CeePlusPlus TemplateMetaprogramming.
The TestCollector pattern in C++ sometimes has this problem. To automatically collect all cases into suites, some test rigs use an external script to harvest them and write a C++ suite.
Level 6: The Intepreter / Framework
The limiting case of Greenspunning: an interpreter for the high-level language (or an extended language containing the desired feature) is written in the low-level language, which then executes code in the high-level language at runtime. Again, when done as a clean coherent design, not really
GreenSpunning; otherwise it's just
AlternateHardAndSoftLayers -- but most developed as mission-critical private tools are unfortunately
ad hoc. Numerous scripting languages such as
ToolCommandLanguage and
LuaLanguage are often used in this manner.
I like these levels, but I object to all those special exceptions.
AlternateHardAndSoftLayers is something you do because at least one of your languages is insufficient (not secure enough, not flexible enough) for both. Using an external tool rather than a library for the
DomainSpecificLanguage elements suggests your language isn't as flexible as it could be.
See:
PhilipGreenspun,
GreenspunsTenthRuleOfProgramming,
FourLevelsOfFeature