Hacker News new | past | comments | ask | show | jobs | submit login

  Greenspun's Tenth Rule of Programming
  Any sufficiently complicated C or Fortran program
  contains an ad-hoc, informally-specified bug-ridden slow 
  implementation of half of Common Lisp.
Replace C by Lisp and CL by Haskell? Rinse, lather, repeat every few decades?



FWIW,

> "Any sufficiently large test suite will contain an ad-hoc, informally-specified, bug-ridden, slow implementation of half of the Haskell type system" -- Smith's Law


This point has been argued far more eloquently and accurately by Cardelli and Wagner, "On Understanding Types, Data Abstraction, and Polymorphism".

http://lucacardelli.name/Papers/OnUnderstanding.A4.pdf

See Section 1.3 "Kinds of Polymorphism" (there is a typo in the paper and section 1.4 is mislabeled as "1.3" as well.)


Can you please give us some historical examples where this quote could be applied? This would be interesting to know.


AutoCAD and Emacs would be literal examples of "sufficiently advanced" C programs by this definition.

My guess is that it is intended to cover any C or Fortran program that includes an ad-hoc interpreter, an ad-hoc dynamic type system, or an ad-hoc garbage collector. That would include e.g. sendmail (at least an ad-hoc interpreter) and GCC (all three).

My guess is that most C programs (I don't know about Fortran) we would intuitively call "complex" contains one of the three technologies, making it harder to come up with a clear counter-example. Some might avoid the "ad-hoc" part by linking with a generic extension language like tcl or lua. Or even Common Lisp.


Well, almost any big traditional application (not really web apps) eventually grows a scripting language for extensions and / or user macros. Basic (in Office), Javascript and Java (in web browsers), Lisp (in the above applications, and probably many more), Lua (in a lot of games), AppleScript, that C thingy in Quake ...

Lisp is relatively easy to implement, powerful, and intuitive to non-programmers (compared to OOP - Python, Perl, and Ruby are also easy but nowhere near as old); so it's a common choice.


I didn't believe this "Easy to implement" line but over Christmas I wrote my own LISP implementation on top of .NET and it comes to about 350 lines codes.

That includes all the list operations, an arbitrary precision number type and a host of the usual built in function (add, subtract, multiply, divide, and not or etc).

Eye-opening to say the least!


A real-life example. I worked on the call routing system that is used by large cable companies and a large satellite TV provider. When a call comes in, the computers dynamically routes the call to the best place to handle the call. It needs to use all kinds of business rules to make the determination. For example, is there an outage in the customer's area? Are we running a special promotion in that area that this call is likely related to? Is the customer's account on hold with our credit department?

All of these decision points, along with what could happen depending on how those decision points get evaluated, end up being things that are defined by the end user (that is, by the IT department at the call center, rather than by us, the original developers of this software). For example, if there's an outage in their area right now, play this specific outage message, then prompt them to see if they want to do something else-- a dynamic rule that'll only be in place for a few hours till the outage is done. Before you know it, you've essentially implemented a programming language within the programming language.

This pattern ends up presenting itself again and again, in many systems that I've implemented. Other systems that I've done with user-defined rules that become essentially programming languages include fraud detection systems, call center flow guides/scripts, systems that help users customize their products for things like: engraving (for trophies or stationery), building computers, building ten-speed bikes, or configuring options for custom-built caskets.

Regarding the customization of caskets or couches or any other custom-built good, this also becomes very much like a programming language. For example, if the user selects leather, then these fabric protection options become available and cost this much, but if they select fabric, then Scotch guard and some other options become available. If they select this group of options, then the manufacturing will have to be outsourced to such-and-such company because they're the only ones that can do that process, but otherwise we manufacture it over here. And so on. All of these things we want to be set up by the people who purchased the software from us, and are not to be coded directly by us when we write the software.

This pattern of needing to express what amounts to code from within the application data becomes quite common once a system gets beyond a certain level of complexity.


Another example is that complicated systems often get to the point where a great deal of their functionality becomes highly configurable. Where they are essentially either creating their own scripting language (less common today, but this was much more common a decade ago), or reading a great deal of data to determine their runtime configuration. Taken to an extreme, you get to where the lines between data and code start to become blurred. When the code being executed at runtime is really a series of functions that are dynamically strung together, you're starting to make a list-like system, arguably.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: