Article View: comp.lang.misc
Article #3238Re: The powerlessness of Lisp
From: Dan Bernstein
Date: Thu, 28 Mar 1991 04:56
Date: Thu, 28 Mar 1991 04:56
436 lines
19149 bytes
19149 bytes
In article <1991Mar26.165516.13035@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
> Byte copying is trivial in Common Lisp.
So translate *(int *)&buf = n; into Lisp. Here char *buf; int n.
> A typical
> "portable" C program running on n different platforms is usually n different
> programs selected by conditional compilation via #ifdef's.
What a load of crap. My latest compressor, for example, has so far been
reported to work on platforms from about fifty vendors. Four of the
configuration options enable optimizations that depend on available
libraries. One enables extra code to handle a common stdio bug in older
systems. Four set defaults for user options. The rest select between
machine-independent optimizations. There aren't any #ifdefs other than
the configuration options. This is hardly atypical of C programs.
> Emacs is written in elisp.
What a(nother) load of crap. Next Doug will be claim that sh, csh, and
ksh are written not in C, but in shell code! After all, the vast
majority of code that people use while executing the shell is, indeed,
in an interpreted language, even if under the scenes there's that dirty
C code actually running and doing all the work.
> The major advantage of lisp over C here is the fact that
> lisp is much more easily extensible.
Yep, and the major advantage of sh over C here is the fact that sh is
much more easily extensible. Do I conclude that sh is written in sh?
Yes or no?
> you are quite outrageous
So who's abusing the English language? :-)
> and completely
> ignored my request for the literature you claim to have read showing that
> software development and testing is faster in C than in Common Lisp.
I never made such a claim. I said that compile time and run time were
slower in dynamically typed languages; later I amended that to ``compile
time or run time.'' More precisely, the literature shows the run time in
dynamically typed languages as much slower than in statically typed
languages. Research (mostly recent) on optimization of dynamically typed
languages shows that the run time can come close (i.e., better than half
the speed), but only at a huge expense in compile time. I believe these
comments correctly summarize the relevant literature, and if you stop
perverting my statements but are still too lazy to do your own homework,
I'll give you sample references.
> As for compose, your response was repeatedly,
[ Doug exhibits his creative writing skills ]
> If you really had
> the stuff, prove it.
Enclosed is another copy of the first article, since you didn't respond
to any of my offers via email. This qualifies you as a royal asshole, by
the way. Also enclosed for completeness are references to your first two
articles implying that my compose() didn't work, and, just in case, one
of the intermediate articles that you lied about.
The interested reader (I doubt there are any) will note that my
compose() nests properly, while Doug has said repeatedly that it
doesn't. As I recall, he also claims to have been reading comp.lang.misc
for more than three months.
> You bristle when asked for any evidence that what you're saying isn't just
> hot air.
Yes, I do, as the challenges come from a perverting pain in the butt.
I don't believe I have left any of your ``questions'' unanswered; I do
hope that you learn some civility before you have the nerve to show your
userid again in this newsgroup. If you claim once more that my compose()
doesn't nest properly, or that I have been reticent in providing
evidence that it does, I will feel no compunction in thrashing you in
public for the next twenty mistakes you make. Don't take this as a
threat, though; I don't want you to tell the truth until you understand
that it really is the truth.
---Dan
Path: kramden.acf.nyu.edu!brnstnd
From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
Message-ID: <19468:Dec2100:23:0790@kramden.acf.nyu.edu>
Date: Fri Dec 21 00:23:07 GMT 1990
Newsgroups: comp.lang.misc
Subject: Look, Ma, I can dynamically compose functions in C!
X-Original-Subject: Re: Complexity of syntax
References: <20@garth.UUCP> <27534.276e5bd3@kuhub.cc.ukans.edu> <1990Dec19.222059.6878@mathrt0.math.chalmers.se>
Organization: IR
In article <1990Dec19.222059.6878@mathrt0.math.chalmers.se> augustss@cs.chalmers.se (Lennart Augustsson) writes:
> To see the difference just try to write a function
> that does function composition.
Okay. (What follows isn't tested but you'll get the idea.)
We'll work with a function descriptor type:
struct basicfun { int (*f)(); } ;
struct twofun { struct fun *first; struct fun *second; }
struct fun { int type;
union { struct basicfun b; struct twofun t; } u;
} ;
#define BASICTYPE 1
#define TWOTYPE 2
To convert a C function pointer into one of these things, given storage
space:
struct fun *cftofun(c,f)
int (*c)();
struct fun *f;
{
f->type = BASICTYPE;
f->u.b.f = c;
return f;
}
To call one of these things, given the argument:
int callfun(f,x)
struct fun *f;
int x;
{
switch(f->type)
{
case BASICTYPE: return f->u.b.f(x);
case TWOTYPE: return callfun(f->u.t.second,
callfun(f->u.t.first,x));
}
}
Finally, to answer the question:
struct fun *compose(second,first,f)
struct fun *second;
struct fun *first;
struct fun *f;
{
f->type = TWOTYPE;
f->u.t.first = first;
f->u.t.second = second;
return f;
}
Of course, a more complete implementation would manage struct fun
storage, possibly with garbage collection.
A different strategy is to store basic functions as just pointers, and
composed functions as a pointer to a special function, followed by the
first and second pointers; then pointers to these ``objects'' would be
passed in as arguments.
Back to Lennart:
> I claim that this is impossible to do in a portable way.
You were saying?
---Dan
Path: kramden.acf.nyu.edu!brnstnd
From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
Newsgroups: comp.lang.misc
Subject: Re: On whether C has first-class composable functions
Message-ID: <25199:Feb801:33:1191@kramden.acf.nyu.edu>
Date: Fri Feb 8 01:33:11 GMT 1991
References: <1991Feb6.161639.18311@spool.cs.wisc.edu> <12547:Feb621:05:4491@kramden.acf.nyu.edu> <1991Feb7.150537.9257@spool.cs.wisc.edu>
Organization: IR
Lines: 99
In article <1991Feb7.150537.9257@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
> Unfortunately, this doesn't solve the problem. Your `functions' are not
> functions. What happens when I pass a Bernstein `function' to twalk(3c)??
``Unfortunately, your bignum package doesn't solve the problem. Your
`bignums' are not numbers. What happens when I pass a DECWRL bignum to
getcwd()??''
The mistake here is the second statement. Bignums are numbers; they just
aren't the same as C's integers. Similarly, anything supporting certain
operations is a function; it doesn't have to be the same as C's
functions.
Your ``problem'' of passing a non-C-function to twalk() has been quite
thoroughly addressed in other postings. Just because twalk() only
accepts C functions doesn't mean that other functions aren't functions,
either in theory or in practice.
This has all been discussed to death before in this newsgroup. If you're
trying to contribute something, make an effort to see what's already
been contributed.
> The question was NEVER, "Can C _implement_ dynamically allocable functions?"
I chose the subject line (I choose most subject lines in comp.lang.misc
these days) and I was using ``L has X'' to mean ``X can be implemented
in L'' where L is a language and X is a semantic feature. Apparently
people can't stand this usage, although nobody's been able to come up
with any other sensible definition of ``has'' in this context; so I've
stopped using ``has'' in this way. Nevertheless, that's what it means in
the subject line.
This has also been discussed to death before in this newsgroup. If you're
trying to contribute something, make an effort to see what's already
been contributed.
> I can implement a Turing machine simulator in practically any language,
> but it's not very interesting or useful.
(Not in Fortran.) The reason that a Turing machine simulator isn't
useful is that once you get down from theory to practice, you care about
issues like efficiency. However, usefulness is not the same thing as
power. Would you say that the original Forth doesn't have I/O facilities
just because its I/O facilities aren't very useful? No.
> Does C _have_ dynamically allocable functions?
> No.
What's your definition of ``has'' for a semantic feature? I'll bet that
your definition will either be (1) syntactic, in which case you're
confusing syntax and semantics; or (2) so ambiguous as to be useless; or
(3) in agreement with mine.
> Compose has a simple mathematical definition, and since Dan is so proud
> of his math, he surely knows that (f o g) o h = f o (g o h).
> (Strangely he expressed confusion over a nested call to compose in a
> posting made by someone else some time ago, but this is really quite
> elementary.)
*** NOTE ADDED 3/27/91: The ``confusion'' is my quote ``What are you
talking about'' when faced with a nonsensical nested compose(). See
the article quoted at the end of this one.
That call was improperly formed and nonsensical as both a mathematical
expression and a C language expression.
[ composing three functions in a row ]
> Let's see Bernstein's compose function do that.
*** NOTE ADDED 3/27/91: This is the first time Doug implied that my
compose() didn't work as advertised.
Are you shooting from the hip, or are you simply confused? It is trivial
to compose() twice in a row.
> (On a related note,
> he also claimed that it is just as easy to prove program correctness in
> C as it is in a functional language.
Well, no, that's not really what I claimed, but I'll let this slide.
> Since his implementation of compose
> in C doesn't obey one of the most trivial identities for that function,
> I wonder how he reaches that bizarre conclusion.)
You are simply confused.
> P.S. Dan, read _The_Structure_and_Interpretation_of_Programming_Languages_,
> by Abelson, Sussman and Sussman. Jim Giles said he didn't learn
> anything useful from that book, but I certainly did and you might too.
I second Jim's opinion.
> At the very least it will show you what you can do with first-class
> functions. (A short preview: blocks, delayed evaluation,
> call-by-name, own variables, coroutines, non-local exits and
> objects for OOP.)
Ah! Finally you come down out of the fluff and get to some real issues.
As I noted in the previous article, I have found very little use for
first-class functions in real-world problems. All of the applications
you mention can easily be handled in C---and some of them, such as
coroutines and so-called ``objects,'' simply don't gain anything from
first-class functions.
---Dan
Path: kramden.acf.nyu.edu!brnstnd
From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
Newsgroups: comp.lang.misc
Subject: Re: On whether C has first-class composable functions
Message-ID: <6828:Feb906:14:3491@kramden.acf.nyu.edu>
Date: Sat Feb 9 06:14:34 GMT 1991
References: <1991Feb7.150537.9257@spool.cs.wisc.edu> <25199:Feb801:33:1191@kramden.acf.nyu.edu> <1991Feb8.191014.6430@spool.cs.wisc.edu>
Organization: IR
Lines: 96
In article <1991Feb8.191014.6430@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
> In article <25199:Feb801:33:1191@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >I chose the subject line (I choose most subject lines in comp.lang.misc
> >these days) and I was using ``L has X'' to mean ``X can be implemented
> >in L'' where L is a language and X is a semantic feature. Apparently
> This is not the meaning of ``has''. X can be implemented in L is a
> meaningless statement for any languages that are Turing equivalent.
First of all, most real languages are not equivalent to Turing machines.
People commonly use one of two models for programs. The first says,
roughly, that a program is valid if its memory use is bounded by a fixed
amount over all possible inputs. (This is for people who don't worry
about running out of memory.) The second says, roughly, that a program
is valid if its memory use is between N and N+K for all inputs, where N
depends on the program and K does not. (This is for when you are
worrying about running out of memory.) Both models suffice for real
languages. Neither model allows a Turing machine. That's why ``has''
does distinguish languages that have, e.g., dynamic allocation from
languages that don't.
Second, you didn't respond to my challenge to provide a useful
definition of ``L has X'' for L a language and X a semantic feature. I
claim that my definition is (1) unambiguous and (2) useful. Why do I say
it's useful? Because ``has'' is a helper word. Sure, the statement ``C
has first-class functions'' (meaning ``first-class functions can be
implemented in C'') doesn't say much. But you can qualify it! You can
say ``C has efficient first-class functions'' (``first class functions
can be implemented efficiently in C'') or ``C has easy-to-use
first-class functions'' or ``C has easy-to-implement first-class
functions.''
> Meaningless terminology is not useful,
Nevertheless, it has been defined for the purposes of this discussion,
so it is no longer meaningless in context.
> and quite frankly Dan, I challenge
> you to give me evidence that _anyone_ uses ``has'' in the sense(lessness)
> that you do.
Webster's, definition 5c(b): ``exercise.'' Their example: ``have mercy
on us.'' ``Mercy'' is a trait---a semantic feature. ``Doug Quale has
mercy on us'' means that you stop rehashing every little bit of a dead
discussion---uh, I mean, that Doug Quale exercises mercy, i.e., Doug
combines his primitive operations to implement mercy. ``Doug has mercy
upon you'' doesn't mean that mercy is one of Doug's *basic* traits, or
that mercy is defined as part of Dougginess, or that Doug *always*
exercises mercy, or that Doug can show mercy without outside help;
similarly for ``C has dynamically allocatable functions.'' And, before
you post some irrelevant quibble, let me point out that this definition
of ``has'' can be applied to impersonal, inactive objects: ``inetd.conf
has control over your connections.''
> I don't think I can say anything more about this.
Then don't.
> >That call was improperly formed and nonsensical as both a mathematical
> >expression and a C language expression.
> Dan, wtf are you talking about??
You referred to the time when I expressed confusion over the supposed
meaning of somebody's nested compose() call. In case you don't remember,
the call in question tried to compose the compose function with an
integer function. Once again, that call was improperly formed and
nonsensical as both a mathematical expression and a C language
expression.
> square o square o square
> is perfectly sensible as a mathematical expression.
Yes.
[ about the square examples again ]
> And yes, Dan, I specifically request you to try explain what is nonsensical
> about those expressions.
I never said that those expressions were nonsensical. Your implication
is a lie, plain and simple. I doubt you have the integrity to review the
articles and apologize, but I'll give you one chance to do so before I
start quoting things in public.
> Instead of continually saying it's trivial, post your compose code in C and
> then we'll see how it stacks up.
I did. Since you apparently would rather flame than think, here's the
three-way composition that you claim to be so difficult. I've written it
out step-by-step and put in comments just for you.
compose(square,square,sqsq) /* put square o square in sqsq */
compose(square,sqsq,sqsqsq) /* put square o sqsq in sqsqsq */
printf("%d\n",apply(sqsqsq,2)); /* apply sqsqsq to 2 and print it */
Exercise: write the missing struct fun definitions and initializations.
---Dan
Path: kramden.acf.nyu.edu!brnstnd
From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein)
Message-ID: <13759:Jan800:19:2391@kramden.acf.nyu.edu>
Date: Tue Jan 8 00:19:23 GMT 1991
Newsgroups: comp.lang.misc
Subject: Re: Re^2: On whether C has first-class composable functions
References: <442@data.UUCP> <4408:Jan421:44:3391@kramden.acf.nyu.edu> <443@data.UUCP>
Organization: IR
In article <443@data.UUCP> kend@data.UUCP (Ken Dickey) writes:
> SCHEME also permits the treatment of functions as full flegded data
> objects; they may be passed as arguments, returned as values, made
> part of composite data structures, and notated as independent, unnamed
> ("anonymous") entities. {Contrast this with most ALGOL-like
> languages, in which a function can be written only by declaring it and
> giving it a name; imagine being able to use an integer value only by
> giving it a name in a declaration!).
``Full-fledged data objects,'' yes; but ``first-class'' doesn't mean
``full-fledged.''
> More recently, [Kent Dybvig, "The Scheme Programming Language",
> Prentice Hall, 1987]
> ...procedures are not always named. Instead, procedures are
> first-class data objects similar to strings or numbers; identifiers
> are bound to procedures in the same way they are bound to other
> objects.
Okay, that'd do it; but if that's the definition of ``first-class'' then
you can have first-class objects that you can't pass as function
arguments! I don't think any of us agree with that.
Anyone want to contribute more definitions?
> > > By the way, what function would "apply(compose(compose,f),x);" return in C?
> > > Strike "composable"?
> > What are you talking about?
[ explanation ]
Okay, you're saying that you want compose() to apply to the first
argument of a function with many arguments. This would be more useful
if you also had a way to switch around the arguments to a function---
e.g., to convert f(x,y) to g(y,x). There's no reason that these things
can't be done with exactly the same techniques as the one-argument
compose(), so I don't think your example is a reason to say that we're
not talking about composable functions.
---Dan
Technical Details
Message-ID:
<26146:Mar2804:56:5791@kramden.acf.nyu.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!rpi!uupsi!cmcl2!kramden.acf.nyu.edu!brnstndReferences:
<1991Mar21.123512.22876@daffy.cs.wisc.edu> <16060:Mar2515:41:5691@kramden.acf.nyu.edu> <1991Mar26.165516.13035@daffy.cs.wisc.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!rpi!uupsi!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: comp.lang.misc Subject: Re: The powerlessness of Lisp Message-ID: <26146:Mar2804:56:5791@kramden.acf.nyu.edu> Date: 28 Mar 91 04:56:57 GMT References: <1991Mar21.123512.22876@daffy.cs.wisc.edu> <16060:Mar2515:41:5691@kramden.acf.nyu.edu> <1991Mar26.165516.13035@daffy.cs.wisc.edu> Organization: IR Lines: 436