Newsgroups: comp.lang.lisp
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!news.mathworks.com!newsfeed.internetmci.com!howland.reston.ans.net!ix.netcom.com!netcom.com!wnewman
From: wnewman@netcom.com (Bill Newman)
Subject: Re: no more lisp!
Message-ID: <wnewmanDoLouI.4tB@netcom.com>
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
X-Newsreader: TIN [version 1.2 PL1]
References: <DoD65D.LrE@abs.net> <4ige8c$6io@news1.h1.usa.pipeline.com> <raffael-2003951649060001@macav.tiac.net>
Date: Thu, 21 Mar 1996 04:37:30 GMT
Lines: 130
Sender: wnewman@netcom18.netcom.com

Raffael Cavallaro (raffael@tiac.net) wrote:
: In article <4ige8c$6io@news1.h1.usa.pipeline.com>,
: boaz@usa.pipeline.com(Boaz Chow) wrote:


: >  
: > and yes.  Lisp sees data and function the same.  but again, so does today's
: > object programming language like Ada, C++, and Pascal. 
: >  


: No, actually, C and C++ do *not* see functions and data as the same. 

: Here's a quote from _ANSI Common Lisp_ by Paul Graham.

: "Suppose instead [of doing something trivial] you want to write a function
: that takes a number n, and returns a function that adds n to its argument:

: ;Lisp
: (defun addn (n)
:    #'(lambda (x)
:          (+ x n)))

: What does addn look like in C? You just can't write it."
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Paul Graham knows what he's talking about, and I like his books.

: You can't write it in C++ either, because C++ doesn't have lexical
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: closures. Being able to return a pointer to a function is not the same
  ^^^^^^^^
: thing as lexical closures. Why, you may ask would one want them? Such a
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: question could only come from a C/C++ (or Pascal) programmer -another
: quote from Graham's book:
: "You have to think in language to write programs in it, and it's difficult
: to want something you can't describe." C/C++ programmers are trained to
: think in terms of what C/C++ can do, and since it can't do closures, they
: don't know about them, or use them. Nevertheless, they're very useful. So
: is a *real* macro system (which Lisp has), not the simple symbol
: substitution that masquerades as macros in C/C++.

You may be slightly confused about the difference between C and C++.
Alternatively, you may have a very narrow, technical definition of 
lexical closures -- if you want something that specifically bundles
up the lexical environment, then you're right, C++ doesn't do it that
way.  But it's reasonably straightforward to write the equivalent
of ``addn'' in C++ -- see the example program after my sig.  (BTW,
I think you're also right that closures can't be done in Pascal,
but I'm pretty sure that the C++ program below could be translated
into Ada95 without much difficulty.  If you agree not to pick on
20-year-old strongly-typed languages, I'll try not to pick on 
pre-Common-Lisp Lisp.:-)

Re. your remark about macros: yes, a real macro system would be nice.
Instead C and C++ programmers end up writing preprocessors and inline
functions and templates and cpp macros.  This doesn't always do
everything we'd like -- there are some macros in Graham's books that
do things which would be hard to do in C++.  So sometimes we end up
implementing higher-level languages in C. :-) :-)

Another thing that I really, really miss from Lisp is a run-time
environment which includes not only a debugger but a real
read-evaluate-print loop.  Free Common Lisps have this, and free
debuggers like gdb are a pretty poor substitute.

: Sorry, C++ is a hack with object orientation added on as an afterthought
: (worth noting in this context that the original name of C++ was "C with
: objects."").

I am pretty impressed by Stroustrup's ability to maintain a certain
amount of elegance in an impressively backward-compatible language.  I
am less impressed with the ability of the Common Lisp folks to do the
same, but YMMV.  Or are you comparing C++'s kludginess to that of purer
languages like Scheme or ML?

Of course, if you just don't like statically-typed compiled languages,
you're unlikely to be impressed no matter what.  So go on writing your
world-beating programs overnight and showing the world how much better
Lisp is for ordinary applications than the stupid languages everyone
else uses.  (I like Graham's books, but that doesn't mean that I endorse
his more grandiose claims for Lisp.:-)

  Bill Newman
  wnewman@netcom.com

/* a rather literal translation of Paul Graham's ``addn'' example
   into C++.  (A more idiomatic translation would make ``Addn'' a
   class derived from ``Float_Float_Closure'' and use the bare ``Addn''
   constructor instead of a function called ``addn''.) */

#include <iostream.h>

class Float_Float_Closure {
  /* If you had to use lots of closures, you'd probably want to define
     something like ``template<class result, class arg1> Closure1''
     as shorthand for closures of arity (?) one; then instead of 
     defining ``Float_Float_Closure'' you'd write Closure1<float,float>
     and be done. */
public:
  virtual float operator()(float x) = 0;
  virtual ~Float_Float_Closure() {}
};

class Plus_Something : Float_Float_Closure {
private:
  float something;
public:
  Plus_Something(float something_arg) : something(something_arg) {}
  float operator()(float x) { return x + something; }
};

Plus_Something* addn(float x)
{
  return new Plus_Something(x);
}

int main()
{
  Plus_Something plus1(1), plus2point4(2.4);
  Plus_Something& plus9 = *addn(9);
  
  cout << "plus1(12) = " << plus1(12)
       << ", plus2point4(11) = " << plus2point4(11)
       << ", plus9(3) = " << plus9(3) << "\n";

  /* ``delete &plus9;'' here if you don't have GC. */

  return 0;
}
