Loading ...
Sorry, an error occurred while loading the content.

237FW: [XP] Lisp's attractions (was: Polymorphism)

Expand Messages
  • Mike Beedle
    Aug 21, 2002

      Thanks for the intro to Lisp. Lots of good info there.

      Here is something I wrote to the XP list on Lisp
      recently that to some extent is a rehash of
      a point that Richard Gabriel made earlier:

      Lisp is bigger than even its creator thought it would
      ever be and the main cause for this is _serendipity_,
      or emergence if you prefer the term.

      This goes on to show that Feyerabend philosophy of Science is
      of utmost importance and that its tenets need to be
      considered seriously in making progress in a field such as ours.

      I also have to admit here a few things about Lisp:

      1) For years I missed the importance of Lisp. I thought
      it was just another language. It wasn't until
      a couple of years ago that I started to realize there
      was something truly special about it.

      2) Understanding Lisp, I think, it is very key to
      understanding what software is all about and being able to
      contrast the good, the bad and the ugly.

      From that perspective, I've got a better education
      from Richard Gabriel and others on the "patterns-discussion"
      mailing list than most get while getting
      Computer Science Ph. D.s.

      3) My ideas about Paterno, the pattern-oriented language,
      and L4, Lifestreams, Living Metaphor (agents),
      Linda and Lisp, the ideas about simulating organic
      processes in software; would have _never_ seen the light
      had I not implemented them with Lisp. In Lisp is
      possible to do many things that are very difficult, if
      not impossible, in other languages.

      Though I have ran with a variety of Lisp environments, my
      preferred environment these days, btw, is Allegro Franz Lisp
      6.2 with AllegroServ running on both Linux and WinXP. I like
      a lot of their libraries/extensions.

      Get a free trial at:

      But there are many other free implementations of course:

      - Mike

      -----Original Message-----
      From: Mike Beedle [mailto:beedlem@...]
      Sent: Wednesday, July 31, 2002 2:46 AM
      To: extremeprogramming@yahoogroups.com
      Subject: RE: [XP] Lisp's attractions (was: Polymorphism)

      George Paci wrote:
      > Kevin Lawrence wrote:
      > > Strangely enough, I wrote a lisp compiler a few weeks ago while
      > > experimenting with genetic programming and I have to confess
      > that I do not
      > > understand the merits of that language at all.
      > Compiler, or interpreter? A bit of Lisp lore: the very first Lisp
      > interpreter was written in a few weeks, by a graduate student whom
      > McCarthy had advised not to try.

      The most amazing thing is what Lisp ended up being out of
      pure serendipity. McCarthy was going after a universal function
      that would compete or replace a Turing machine.

      But when S.R. Russell noticed that eval could serve as an interpreter
      for LISP, and promptly coded it -- against McCarthy's advise and
      wishes, we ended up with a very special programming language, where
      code is always data, and data can be code!!, where a simple
      interpreter and a handful of primitives define a powerful language:

      (define (eval exp env)
      (cond ((self-evaluating? exp) exp)
      ((variable? exp) (lookup-variable-value exp env))
      ((quoted? exp) (text-of-quotation exp))
      ((assignment? exp) (eval-assignment exp env))
      ((definition? exp) (eval-definition exp env))
      ((if? exp) (eval-if exp env))
      ((lambda? exp)
      (make-procedure (lambda-parameters exp)
      (lambda-body exp)
      ((begin? exp)
      (eval-sequence (begin-actions exp) env))
      ((cond? exp) (eval (cond->if exp) env))
      ((application? exp)
      (apply (eval (operator exp) env)
      (list-of-values (operands exp) env)))
      (error "Unknown expression type - EVAL" exp))))

      (define (apply procedure arguments)
      (cond ((primitive-procedure? procedure)
      (apply-primitive-procedure procedure arguments))
      ((compound-procedure? procedure)
      (procedure-body procedure)
      (procedure-parameters procedure)
      (procedure-environment procedure))))
      "Unknown procedure type - APPLY" procedure))))

      Understanding this "universal function" is equivalent as
      understanding a 400 page programming language.

      To prove that McCarthy had little intention in doing this,
      take a look at what he wrote:

      "Another way to show that LISP was neater than Turing machines
      was to write a universal LISP function and show that it is
      briefer and more comprehensible than the description of a
      universal Turing machine. This was the LISP function eval[e,a],
      which computes the value of a LISP expression e - the
      second argument a being a list of assignments of values
      to variables. (a is needed to make the recursion work). Writing
      eval required inventing a notation representing LISP
      functions as LISP data, and such a notation was devised for
      the purposes of the paper with no thought that it would
      be used to express LISP programs in practice. Logical
      completeness required that the notation used to express
      functions used as functional arguments be extended to
      provide for recursive functions, and the LABEL notation
      was invented by Nathaniel Rochester for that purpose.
      D.M.R. Park pointed out that LABEL was logically unnecessary
      since the result could be achieved using only LAMBDA - by
      a construction analogous to Church's Y-operator, albeit
      in a more complicated way."


      Which goes to show that he had _no_ vision or plan to
      create the monster that he did: it just happened out of
      pure luck. (Feyerabend lives!) This statement is specially

      "Writing eval required inventing a notation representing
      LISP functions as LISP data, and such a notation was
      devised for the purposes of the paper with no thought
      that it would be used to express LISP programs in practice."

      Thank God someone took his original notation seriously and
      literally .... otherwise, Lisp as we know it, may have never
      existed. And humanity would be deprived of its power, flexibility
      and simplicity.

      In terms of impact, Genetic programming, most Agent Technology,
      Artificial Intelligence and all of its branches (Logical programming,
      Rule-Oriented, Natural Language Processing, Neural Nets, Game
      Programming, etc. etc.), Hybrid or Multi-Paradigmic programming,
      Aspect Oriented Programming, Meta-Object Protocols, and a great
      deal of programming language research could have never been
      possible if it wasn't for Lisp.

      Literally, we would not be where we are in programming if
      it wasn't for a crazy guy that took a programming language
      research paper literally, and did a very dumb thing:

      wrote some code in a short amount of time.

      The rest was generated by this little "historical accident".

      George Paci wrote:
      > I think you're getting close to what's great about Lisp. Basically,
      > you're typing in parse trees. There's very little syntactic sugar
      > to get between you and the interpreter (or compiler, these days).
      > Since you've got your program in a form that's so easy for other
      > programs to deal with, you can write very useful macros -- Lisp code
      > that changes other Lisp code.

      Yes, absolutely, once code is data, there is not need for
      ASTs (Abstract Syntax Trees). Lisp notation is basically a condensed
      form for writing ASTs.

      But what that means is that to modify the meaning of the
      language and/or to do even things like meta-programming, Lisp
      is the natural choice. Think about this: it is easy to generate
      data from a program, right? Well, if code is data, then it
      is easy to generate _code_. Things like genetic programming are
      easy with Lisp.

      Also, parsing "other languages" is easy with Lisp. It is no
      coincidence that most ACLs (Agent Communication Languages) are
      Lisp-based, because the "verb/data exchanges" can be simply
      interpreted on either side. No need for SAX-like parsers that
      waste cycles in serialization and deserialization -- simply
      take the stream and interpret it. And if it is not exactly Lisp,
      get inspired by Lisp and create an eval-like function and then
      interpret the "new language". In that sense, eval is like a
      "universal SAX parser". Wouldn't you like to have one of those?

      On the meta-programming side, imagine this, you can set any
      level of filtering, execution of extra actions, change interpretation,
      or give new meanings to anything that is interpreted or
      "evaluates" by just changing eval. So if you want to keep
      meta data or meta processing on your programs there is nothing
      as simple as Lisp.

      In Lisp, for example, is incredibly easy to do Aspect Oriented
      Programming because you can manage at every point what happens
      to the joint and cut points of functions and it is easy
      to do so.... everything goes through eval.

      If that wasn't enough, Lisp comes with a myriad of nice features
      such as lambdas (first order functions), closures (functions that
      generate functions), powerful macros (that can generate anything
      data, functions, classes, patterns, or even other macros),
      generics (methods that cut across multiple classes in CLOS), and
      by extension, MOPs; and with a wide variety of powerful
      Open Source Lisp source code scattered throughout the planet.
      (The Lisp community was perhaps the first community that
      embraced Open Source.)

      In my opinion, Lisp is the most powerful and flexible language,
      and in fact, I would say that once you understand Lisp, other
      languages seem very constraining, underpowered and unnecessary

      Also, Lisp programmers were probably the first "agile developers"
      on the planet, because as far back as the mid-60s, many of the
      practices that we know today as "agile practices" or even
      "extreme programming" were already in practice:

      - Bottom-up Design. LISP programmers have practiced
      bottom-up design since the 60s. So bottom-up architecting
      and emergent design have lived in this community from
      the very beginning.

      - Test-first programming In LISP you test everything
      with eval all the time. Also it is customary to write
      libraries by writing tests at the end of source code
      that get commented when the source code is released.
      The test are typically test evaluations that you
      want to remember.

      - Development in pairs. This was used to mentor
      juniors through the "buddy system". Practiced at
      MIT, for example.

      - Customer-Driven implementations with rapid
      prototyping being practiced. It is easier
      to show the customer what he or she may want
      in LISP than to write a long document

      - Continuous Integration, since individual developer's
      speed was high, continuous integration was
      necessary and mandatory

      - Iterative Development, was natural since
      development was goal-oriented


      Sorry for my longish post -- I could rave and rant all day about
      the powers of Lisp.

      I'll leave you with a thought. Here is simple example to
      extend Lisp to do Object-Oriented programming. Try to do something
      similar in C, C++, Java or even Smalltalk ;-)

      (defmacro define-class (class inst-vars class-vars &body methods)
      "Define a class for object-oriented programming."
      ;; Define constructor and generic functions for methods
      `(let ,class-vars
      (mapcar #'ensure-generic-fn ',(mapcar #'first methods))
      (defun ,class ,inst-vars
      #'(lambda (message)
      (case message
      ,@(mapcar #'make-clause methods))))))

      (defun make-clause (clause)
      "Translate a message from define-class into a case clause."
      `(,(first clause) #'(lambda ,(second clause) .,(rest2 clause))))

      (defun ensure-generic-fn (message)
      "Define an object-oriented dispatch function for a message,
      unless it has already been defined as one."
      (unless (generic-fn-p message)
      (let ((fn #'(lambda (object &rest args)
      (apply (get-method object message) args))))
      (setf (symbol-function message) fn)
      (setf (get message 'generic-fn) fn))))

      (defun generic-fn-p (fn-name)
      "Is this a generic function?"
      (and (fboundp fn-name)
      (eq (get fn-name 'generic-fn) (symbol-function fn-name))))

      - Mike

      To Post a message, send it to: extremeprogramming@...

      To Unsubscribe, send a blank message to:

      ad-free courtesy of objectmentor.com

      Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
    • Show all 3 messages in this topic